get token for user, post users, get all users, post thought, get all thoughts. runs ok
@@ -0,0 +1,6 @@
+module.exports = { + + 'secret': 'secretfortoken', + 'database': 'mongodb://localhost/thoughts' + +};
@@ -2,6 +2,14 @@ //File: controllers/tvshows.js
var mongoose = require('mongoose'); var userModel = mongoose.model('userModel'); +/* */ +var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens +var express = require("express"); +var app = express(); +var config = require('../config'); // get our config file +app.set('superSecret', config.secret); // secret variable +/* */ + //GET - Return all tvshows in the DB exports.findAllUsers = function(req, res) { userModel.find(function(err, users) {@@ -29,9 +37,11 @@ console.log(req.body);
var user = new userModel({ username: req.body.username, + password: req.body.password, description: req.body.description, icon: req.body.icon, - mail: req.body.mail + mail: req.body.mail, + admin: req.body.admin }); user.save(function(err, user) {@@ -68,3 +78,42 @@ console.log('DELETE /activities/' + req.params.id);
}) }); }; + + +//POST - auth user +exports.login = function(req, res) { + // find the user + userModel.findOne({ + username: req.body.username + }, function(err, user) { + + if (err) throw err; + + if (!user) { + res.json({ success: false, message: 'Authentication failed. User not found.' }); + } else if (user) { + + // check if password matches + if (user.password != req.body.password) { + res.json({ success: false, message: 'Authentication failed. Wrong password.' }); + } else { + + // if user is found and password is right + // create a token + var token = jwt.sign(user, app.get('superSecret'), { + //expiresInMinutes: 1440 // expires in 24 hours + expiresIn: '10m' + }); + + // return the information including token as JSON + res.json({ + success: true, + message: 'Enjoy your token!', + token: token + }); + } + + } + + }); +};
@@ -15,8 +15,10 @@ });*/
var userSchema = new Schema({ username: { type: String }, + password: { type: String }, description: { type: String }, icon: { type: String }, - mail: { type: String } + mail: { type: String }, + admin: { type: Boolean } }) module.exports = mongoose.model('userModel', userSchema);
@@ -114,6 +114,5 @@ "shasum": "1f88aba4ab0b1508e8312acc39345f36e992e2f2",
"tarball": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "readme": "ERROR: No README data found!" + "_resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz" }
@@ -27,7 +27,7 @@ "cache"
], "repository": { "type": "git", - "url": "https://github.com/jshttp/fresh" + "url": "git+https://github.com/jshttp/fresh.git" }, "devDependencies": { "istanbul": "0.3.9",@@ -82,5 +82,6 @@ "shasum": "651f838e22424e7566de161d8358caa199f83d4f",
"tarball": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" }, "directories": {}, - "_resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" + "_resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "readme": "ERROR: No README data found!" }
@@ -0,0 +1,22 @@
+{ + "evil": true, + "regexdash": true, + "browser": true, + "wsh": true, + "trailing": true, + "sub": true, + "unused": true, + "undef": true, + "laxcomma": true, + "node": true, + "browser": false, + "esnext": true, + "globals": { + "describe": true, + "it": true, + "require": true, + "atob": false, + "escape": true, + "before": true + } +}
@@ -0,0 +1,6 @@
+language: node_js +before_install: npm i -g npm@1.4.28 +node_js: + - "5" + - "4" + - "0.12"
@@ -0,0 +1,266 @@
+# Change Log + + +All notable changes to this project will be documented in this file starting from version **v4.0.0**. +This project adheres to [Semantic Versioning](http://semver.org/). + +## 7.1.2 - 2016-07-12 + + - do not stringify the payload when signing async - closes #224 ([084f537d3dfbcef2bea411cc0a1515899cc8aa21](https://github.com/auth0/node-jsonwebtoken/commit/084f537d3dfbcef2bea411cc0a1515899cc8aa21)), closes [#224](https://github.com/auth0/node-jsonwebtoken/issues/224) + +## 7.1.1 - 2016-07-12 + + - do not mutate options in jwt.verify, closes #227 ([63263a28a268624dab0927b9ad86fffa44a10f84](https://github.com/auth0/node-jsonwebtoken/commit/63263a28a268624dab0927b9ad86fffa44a10f84)), closes [#227](https://github.com/auth0/node-jsonwebtoken/issues/227) + - refactor into multiple files ([e11d505207fa33501298300c9accbfb809d8748d](https://github.com/auth0/node-jsonwebtoken/commit/e11d505207fa33501298300c9accbfb809d8748d)) + +## 7.1.0 - 2016-07-12 + + - Exp calculated based on iat. fix #217 ([757a16e0e35ad19f9e456820f55d5d9f3fc76aee](https://github.com/auth0/node-jsonwebtoken/commit/757a16e0e35ad19f9e456820f55d5d9f3fc76aee)), closes [#217](https://github.com/auth0/node-jsonwebtoken/issues/217) + +## 7.0.0 - 2016-05-19 + + - change jwt.sign to return errors on callback instead of throwing errors ([1e46c5a42aa3dab8478efa4081d8f8f5c5485d56](https://github.com/auth0/node-jsonwebtoken/commit/1e46c5a42aa3dab8478efa4081d8f8f5c5485d56)) + +## 6.2.0 - 2016-04-29 + + - add support for `options.clockTolerance` to `jwt.verify` ([65ddea934f226bf06bc9d6a55be9587515cfc38d](https://github.com/auth0/node-jsonwebtoken/commit/65ddea934f226bf06bc9d6a55be9587515cfc38d)) + +## 6.1.2 - 2016-04-29 + + - fix sign method for node.js 0.12. closes #193 ([9c38374142d3929be3c9314b5e9bc5d963c5955f](https://github.com/auth0/node-jsonwebtoken/commit/9c38374142d3929be3c9314b5e9bc5d963c5955f)), closes [#193](https://github.com/auth0/node-jsonwebtoken/issues/193) + - improve async test ([7b0981380ddc40a5f1208df520631785b5ffb85a](https://github.com/auth0/node-jsonwebtoken/commit/7b0981380ddc40a5f1208df520631785b5ffb85a)) + +## 6.1.0 - 2016-04-27 + + - verify unsigned tokens ([ec880791c10ed5ef7c8df7bf28ebb95c810479ed](https://github.com/auth0/node-jsonwebtoken/commit/ec880791c10ed5ef7c8df7bf28ebb95c810479ed)) + +## 6.0.1 - 2016-04-27 + +This was an immediate change after publishing 6.0.0. + + - throw error on invalid options when the payload is not an object ([304f1b33075f79ed66f784e27dc4f5307aa39e27](https://github.com/auth0/node-jsonwebtoken/commit/304f1b33075f79ed66f784e27dc4f5307aa39e27)) + +## 6.0.0 - 2016-04-27 + + - Change .sign to standard async callback ([50873c7d45d2733244d5da8afef3d1872e657a60](https://github.com/auth0/node-jsonwebtoken/commit/50873c7d45d2733244d5da8afef3d1872e657a60)) + - Improved the options for the `sign` method ([53c3987b3cc34e95eb396b26fc9b051276e2f6f9](https://github.com/auth0/node-jsonwebtoken/commit/53c3987b3cc34e95eb396b26fc9b051276e2f6f9)) + + - throw error on invalid options like `expiresIn` when the payload is not an object ([304f1b33075f79ed66f784e27dc4f5307aa39e27](https://github.com/auth0/node-jsonwebtoken/commit/304f1b33075f79ed66f784e27dc4f5307aa39e27)) + - `expiresInMinutes` and `expiresInSeconds` are deprecated and no longer supported. + - `notBeforeInMinutes` and `notBeforeInSeconds` are deprecated and no longer supported. + - `options` are strongly validated. + - `options.expiresIn`, `options.notBefore`, `options.audience`, `options.issuer`, `options.subject` and `options.jwtid` are mutually exclusive with `payload.exp`, `payload.nbf`, `payload.aud`, `payload.iss` + - `options.algorithm` is properly validated. + - `options.headers` is renamed to `options.header`. + + - update CHANGELOG to reflect most of the changes. closes #136 ([b87a1a8d2e2533fbfab518765a54f00077918eb7](https://github.com/auth0/node-jsonwebtoken/commit/b87a1a8d2e2533fbfab518765a54f00077918eb7)), closes [#136](https://github.com/auth0/node-jsonwebtoken/issues/136) + - update readme ([53a88ecf4494e30e1d62a1cf3cc354650349f486](https://github.com/auth0/node-jsonwebtoken/commit/53a88ecf4494e30e1d62a1cf3cc354650349f486)) + +## 5.7.0 - 2016-02-16 + + + - add support for validating multiples issuers. closes #163 ([39d9309ae05648dbd72e5fd1993df064ad0e8fa5](https://github.com/auth0/node-jsonwebtoken/commit/39d9309ae05648dbd72e5fd1993df064ad0e8fa5)), closes [#163](https://github.com/auth0/node-jsonwebtoken/issues/163) + + +## 5.6.1 - 2016-02-16 + + + - 5.6.1 ([06d8209d499dbc9a8dd978ab6cbb9c6818fde203](https://github.com/auth0/node-jsonwebtoken/commit/06d8209d499dbc9a8dd978ab6cbb9c6818fde203)) + - fix wrong error when setting expiration on non-object payload. closes #153 ([7f7d76edfd918d6afc7c7cead888caa42ccaceb4](https://github.com/auth0/node-jsonwebtoken/commit/7f7d76edfd918d6afc7c7cead888caa42ccaceb4)), closes [#153](https://github.com/auth0/node-jsonwebtoken/issues/153) + + + +## 5.6.0 - 2016-02-16 + + + - added missing validations of sub and jti ([a1affe960d0fc52e9042bcbdedb65734f8855580](https://github.com/auth0/node-jsonwebtoken/commit/a1affe960d0fc52e9042bcbdedb65734f8855580)) + - Fix tests in jwt.rs.tests.js which causes 4 to fail ([8aedf2b1f575b0d9575c1fc9f2ac7bc868f75ff1](https://github.com/auth0/node-jsonwebtoken/commit/8aedf2b1f575b0d9575c1fc9f2ac7bc868f75ff1)) + - Update README.md ([349b7cd00229789b138928ca060d3ef015aedaf9](https://github.com/auth0/node-jsonwebtoken/commit/349b7cd00229789b138928ca060d3ef015aedaf9)) + + + +## 5.5.4 - 2016-01-04 + + + - minor ([46552e7c45025c76e3f647680d7539a66bfac612](https://github.com/auth0/node-jsonwebtoken/commit/46552e7c45025c76e3f647680d7539a66bfac612)) + + + +## 5.5.3 - 2016-01-04 + + + - add a console.warn on invalid options for string payloads ([71200f14deba0533d3261266348338fac2d14661](https://github.com/auth0/node-jsonwebtoken/commit/71200f14deba0533d3261266348338fac2d14661)) + - minor ([65b1f580382dc58dd3da6f47a52713776fd7cdf2](https://github.com/auth0/node-jsonwebtoken/commit/65b1f580382dc58dd3da6f47a52713776fd7cdf2)) + + + +## 5.5.2 - 2016-01-04 + + + - fix signing method with sealed objects, do not modify the params object. closes #147 ([be9c09af83b09c9e72da8b2c6166fa51d92aeab6](https://github.com/auth0/node-jsonwebtoken/commit/be9c09af83b09c9e72da8b2c6166fa51d92aeab6)), closes [#147](https://github.com/auth0/node-jsonwebtoken/issues/147) + + + +## 5.5.1 - 2016-01-04 + + + - fix nbf verification. fix #152 ([786d37b299c67771b5e71a2ca476666ab0f97d98](https://github.com/auth0/node-jsonwebtoken/commit/786d37b299c67771b5e71a2ca476666ab0f97d98)), closes [#152](https://github.com/auth0/node-jsonwebtoken/issues/152) + + + +## 5.5.0 - 2015-12-28 + + + - improvements to nbf and jti claims ([46372e928f6d2e7398f9b88022ca617d2a3b0699](https://github.com/auth0/node-jsonwebtoken/commit/46372e928f6d2e7398f9b88022ca617d2a3b0699)) + - Remove duplicate payload line (fix bug in IE strict mode) ([8163d698e0c5ad8c44817a5dcd42a15d7e9c6bc8](https://github.com/auth0/node-jsonwebtoken/commit/8163d698e0c5ad8c44817a5dcd42a15d7e9c6bc8)) + - Remove duplicate require('ms') line ([7c00bcbcbf8f7503a1070b394a165eccd41de66f](https://github.com/auth0/node-jsonwebtoken/commit/7c00bcbcbf8f7503a1070b394a165eccd41de66f)) + - Update README to reflect addition of async sign ([d661d4b6f68eb417834c99b36769444723041ccf](https://github.com/auth0/node-jsonwebtoken/commit/d661d4b6f68eb417834c99b36769444723041ccf)) + + + +## 5.4.0 - 2015-10-02 + + + - deprecate expireInMinutes and expireInSeconds - in favor of expiresIn ([39ecc6f8f310f8462e082f1d53de0b4222b29b6f](https://github.com/auth0/node-jsonwebtoken/commit/39ecc6f8f310f8462e082f1d53de0b4222b29b6f)) + + +## 5.3.0 - 2015-10-02 + + + - 5.3.0 ([5d559ced3fbf10c1adae2e5792deda06ea89bcd3](https://github.com/auth0/node-jsonwebtoken/commit/5d559ced3fbf10c1adae2e5792deda06ea89bcd3)) + - minor ([6e81ff87a3799b0e56db09cbae42a97e784716c4](https://github.com/auth0/node-jsonwebtoken/commit/6e81ff87a3799b0e56db09cbae42a97e784716c4)) + + + +## 5.1.0 - 2015-10-02 + + + - added async signing ([9414fbcb15a1f9cf4fe147d070e9424c547dabba](https://github.com/auth0/node-jsonwebtoken/commit/9414fbcb15a1f9cf4fe147d070e9424c547dabba)) + - Update README.md ([40b2aaaa843442dfb8ee7b574f0a788177e7c904](https://github.com/auth0/node-jsonwebtoken/commit/40b2aaaa843442dfb8ee7b574f0a788177e7c904)) + + + +## 5.0.5 - 2015-08-19 + + + - add ms dep to package.json ([f13b3fb7f29dff787e7c91ebe2eb5adeeb05f251](https://github.com/auth0/node-jsonwebtoken/commit/f13b3fb7f29dff787e7c91ebe2eb5adeeb05f251)) + - add note to explain, related to #96 #101 #6 ([dd8969e0e6ed0bcb9cae905d2b1a96476bd85da3](https://github.com/auth0/node-jsonwebtoken/commit/dd8969e0e6ed0bcb9cae905d2b1a96476bd85da3)) + - add tests for options.headers ([7787dd74e705787c39a871ca29c75a2e0a3948ac](https://github.com/auth0/node-jsonwebtoken/commit/7787dd74e705787c39a871ca29c75a2e0a3948ac)) + - add tests for verify expires ([d7c5793d98c300603440ab460c11665f661ad3a0](https://github.com/auth0/node-jsonwebtoken/commit/d7c5793d98c300603440ab460c11665f661ad3a0)) + - add verify option maxAge (with tests) ([49d54e54f7e70b1c53a2e4ee67e116c907d75319](https://github.com/auth0/node-jsonwebtoken/commit/49d54e54f7e70b1c53a2e4ee67e116c907d75319)) + - fix spelling error in error message ([8078b11b224fa05ac9003ca5aa2c85e9f0128cfb](https://github.com/auth0/node-jsonwebtoken/commit/8078b11b224fa05ac9003ca5aa2c85e9f0128cfb)) + - Fix typo options.header is not a documented option + ([5feaa5b962ccbddeff054817a410f7b0c1e6ce7f](https://github.com/auth0/node-jsonwebtoken/commit/5feaa5b962ccbddeff054817a410f7b0c1e6ce7f)) + - update JWT spec link. closes #112 ([f5fa50f797456a12240589161835c7ea30807195](https://github.com/auth0/node-jsonwebtoken/commit/f5fa50f797456a12240589161835c7ea30807195)), closes [#112](https://github.com/auth0/node-jsonwebtoken/issues/112) + + +## 5.0.3 - 2015-07-15 + + - Added nbf support ([f26ba4e2fa197a20497632b63ffcd13ae93aacc4](https://github.com/auth0/node-jsonwebtoken/commit/f26ba4e2fa197a20497632b63ffcd13ae93aacc4)) + - Added support for subject and jwt id ([ab76ec5bc554e2d1e25376ddb7cea711d86af651](https://github.com/auth0/node-jsonwebtoken/commit/ab76ec5bc554e2d1e25376ddb7cea711d86af651)) + - Fix `this` referring to the global object instead of `module.exports` in `verify()` ([93f554312e37129027fcf4916f48cb8d1b53588c](https://github.com/auth0/node-jsonwebtoken/commit/93f554312e37129027fcf4916f48cb8d1b53588c)) + - Fix typo, line 139 README, complete option for .decode. ([59c110aeb8c7c1847ef2ffd77702d13627c89e10](https://github.com/auth0/node-jsonwebtoken/commit/59c110aeb8c7c1847ef2ffd77702d13627c89e10)) + - minor ([61ff1172272b582902313e958058ff22413494af](https://github.com/auth0/node-jsonwebtoken/commit/61ff1172272b582902313e958058ff22413494af)) + + + +## 5.0.2 - 2015-06-15 + + + - fix typo in docs . closes #86 ([3d3413221f36acef4dfd1cbed87f1f3565cd6f84](https://github.com/auth0/node-jsonwebtoken/commit/3d3413221f36acef4dfd1cbed87f1f3565cd6f84)), closes [#86](https://github.com/auth0/node-jsonwebtoken/issues/86) + + + +## 5.0.1 - 2015-05-15 + + + - Add option to return header and payload when decoding. ([7254e011b59f892d1947e6c11819281adac7069d](https://github.com/auth0/node-jsonwebtoken/commit/7254e011b59f892d1947e6c11819281adac7069d)) + - Avoid uncaught "SyntaxError: Unexpected token ͧ" error. ([0dc59cd6ee15d83a606acffa7909ee76176ae186](https://github.com/auth0/node-jsonwebtoken/commit/0dc59cd6ee15d83a606acffa7909ee76176ae186)) + - Document complete option in README. ([ec32b20241a74d9681ea26e1a7024b4642468c00](https://github.com/auth0/node-jsonwebtoken/commit/ec32b20241a74d9681ea26e1a7024b4642468c00)) + - Fix example in README, silence verbose logging. ([ba3174d10033c41e9c211a38f1cc67f74fbd7f69](https://github.com/auth0/node-jsonwebtoken/commit/ba3174d10033c41e9c211a38f1cc67f74fbd7f69)) + - Fix link to auth0.com in README ([1b3c5ff72c9bc25e9271646e679f3080f2a042a0](https://github.com/auth0/node-jsonwebtoken/commit/1b3c5ff72c9bc25e9271646e679f3080f2a042a0)) + - Immediate return if not decoded. ([851bda2b10168f3269c3da6e74d310742f31a193](https://github.com/auth0/node-jsonwebtoken/commit/851bda2b10168f3269c3da6e74d310742f31a193)) + - Prevent throw on undefined/null secret ([0fdf78d4dbf609455f3277d6169a987aef0384d4](https://github.com/auth0/node-jsonwebtoken/commit/0fdf78d4dbf609455f3277d6169a987aef0384d4)) + - Removed path from test ([d6240e24186732d368bffe21143becf44c38f0d6](https://github.com/auth0/node-jsonwebtoken/commit/d6240e24186732d368bffe21143becf44c38f0d6)) + - Simplified checking for missing key ([f1cffd033bffc44f20558eda4a797c3fa2f4ee05](https://github.com/auth0/node-jsonwebtoken/commit/f1cffd033bffc44f20558eda4a797c3fa2f4ee05)) + - Typo ([ffe68dbe0219bab535c1018448eb4c0b22f1f902](https://github.com/auth0/node-jsonwebtoken/commit/ffe68dbe0219bab535c1018448eb4c0b22f1f902)) + - Update CHANGELOG.md ([927cce0dad1bc9aad75aeef53e276cf4cfc0d776](https://github.com/auth0/node-jsonwebtoken/commit/927cce0dad1bc9aad75aeef53e276cf4cfc0d776)) + - Update CHANGELOG.md ([6879e0fdde222995c70a3a69a4af94993d9c667e](https://github.com/auth0/node-jsonwebtoken/commit/6879e0fdde222995c70a3a69a4af94993d9c667e)) + - Update CHANGELOG.md ([c5596c10e8705727fa13e0394184a606083078bc](https://github.com/auth0/node-jsonwebtoken/commit/c5596c10e8705727fa13e0394184a606083078bc)) + - Update CHANGELOG.md ([07541f0315f26d179e1cde92732b6124d6869b6f](https://github.com/auth0/node-jsonwebtoken/commit/07541f0315f26d179e1cde92732b6124d6869b6f)) + - Update CHANGELOG.md ([e6465d48ddd1dc2c3297229b28c78fd5490a2ba9](https://github.com/auth0/node-jsonwebtoken/commit/e6465d48ddd1dc2c3297229b28c78fd5490a2ba9)) + +## [5.0.0] - 2015-04-11 + +### Changed + + - [sign] Only set defautl `iat` if the user does not specify that argument. + + https://github.com/auth0/node-jsonwebtoken/commit/e900282a8d2dff1d4dec815f7e6aa7782e867d91 + https://github.com/auth0/node-jsonwebtoken/commit/35036b188b4ee6b42df553bbb93bc8a6b19eae9d + https://github.com/auth0/node-jsonwebtoken/commit/954bd7a312934f03036b6bb6f00edd41f29e54d9 + https://github.com/auth0/node-jsonwebtoken/commit/24a370080e0b75f11d4717cd2b11b2949d95fc2e + https://github.com/auth0/node-jsonwebtoken/commit/a77df6d49d4ec688dfd0a1cc723586bffe753516 + +### Security + + - [verify] Update to jws@^3.0.0 and renaming `header.alg` mismatch exception to `invalid algorithm` and adding more mismatch tests. + + As `jws@3.0.0` changed the verify method signature to be `jws.verify(signature, algorithm, secretOrKey)`, the token header must be decoded first in order to make sure that the `alg` field matches one of the allowed `options.algorithms`. After that, the now validated `header.alg` is passed to `jws.verify` + + As the order of steps has changed, the error that was thrown when the JWT was invalid is no longer the `jws` one: + ``` + { [Error: Invalid token: no header in signature 'a.b.c'] code: 'MISSING_HEADER', signature: 'a.b.c' } + ``` + + That old error (removed from jws) has been replaced by a `JsonWebTokenError` with message `invalid token`. + + > Important: versions >= 4.2.2 this library are safe to use but we decided to deprecate everything `< 5.0.0` to prevent security warnings from library `node-jws` when doing `npm install`. + + https://github.com/auth0/node-jsonwebtoken/commit/634b8ed0ff5267dc25da5c808634208af109824e + https://github.com/auth0/node-jsonwebtoken/commit/9f24ffd5791febb449d4d03ff58d7807da9b9b7e + https://github.com/auth0/node-jsonwebtoken/commit/19e6cc6a1f2fd90356f89b074223b9665f2aa8a2 + https://github.com/auth0/node-jsonwebtoken/commit/1e4623420159c6410616f02a44ed240f176287a9 + https://github.com/auth0/node-jsonwebtoken/commit/954bd7a312934f03036b6bb6f00edd41f29e54d9 + https://github.com/auth0/node-jsonwebtoken/commit/24a370080e0b75f11d4717cd2b11b2949d95fc2e + https://github.com/auth0/node-jsonwebtoken/commit/a77df6d49d4ec688dfd0a1cc723586bffe753516 + +## [4.2.2] - 2015-03-26 +### Fixed + + - [asymmetric-keys] Fix verify for RSAPublicKey formated keys (`jfromaniello - awlayton`) + https://github.com/auth0/node-jsonwebtoken/commit/402794663b9521bf602fcc6f2e811e7d3912f9dc + https://github.com/auth0/node-jsonwebtoken/commit/8df6aabbc7e1114c8fb3917931078254eb52c222 + +## [4.2.1] - 2015-03-17 +### Fixed + + - [asymmetric-keys] Fixed issue when public key starts with BEING PUBLIC KEY (https://github.com/auth0/node-jsonwebtoken/issues/70) (`jfromaniello`) + https://github.com/auth0/node-jsonwebtoken/commit/7017e74db9b194448ff488b3e16468ada60c4ee5 + +## [4.2.0] - 2015-03-16 +### Security + + - [asymmetric-keys] Making sure a token signed with an asymmetric key will be verified using a asymmetric key. + When the verification part was expecting a token digitally signed with an asymmetric key (RS/ES family) of algorithms an attacker could send a token signed with a symmetric algorithm (HS* family). + + The issue was caused because the same signature was used to verify both type of tokens (`verify` method parameter: `secretOrPublicKey`). + + This change adds a new parameter to the verify called `algorithms`. This can be used to specify a list of supported algorithms, but the default value depends on the secret used: if the secretOrPublicKey contains the string `BEGIN CERTIFICATE` the default is `[ 'RS256','RS384','RS512','ES256','ES384','ES512' ]` otherwise is `[ 'HS256','HS384','HS512' ]`. (`jfromaniello`) + https://github.com/auth0/node-jsonwebtoken/commit/c2bf7b2cd7e8daf66298c2d168a008690bc4bdd3 + https://github.com/auth0/node-jsonwebtoken/commit/1bb584bc382295eeb7ee8c4452a673a77a68b687 + +## [4.1.0] - 2015-03-10 +### Changed +- Assume the payload is JSON even when there is no `typ` property. [5290db1](https://github.com/auth0/node-jsonwebtoken/commit/5290db1bd74f74cd38c90b19e2355ef223a4d931) + +## [4.0.0] - 2015-03-06 +### Changed +- The default encoding is now utf8 instead of binary. [92d33bd](https://github.com/auth0/node-jsonwebtoken/commit/92d33bd99a3416e9e5a8897d9ad8ff7d70a00bfd) +- Add `encoding` as a new option to `sign`. [1fc385e](https://github.com/auth0/node-jsonwebtoken/commit/1fc385ee10bd0018cd1441552dce6c2e5a16375f) +- Add `ignoreExpiration` to `verify`. [8d4da27](https://github.com/auth0/node-jsonwebtoken/commit/8d4da279e1b351ac71ace276285c9255186d549f) +- Add `expiresInSeconds` to `sign`. [dd156cc](https://github.com/auth0/node-jsonwebtoken/commit/dd156cc30f17028744e60aec0502897e34609329) + +### Fixed +- Fix wrong error message when the audience doesn't match. [44e3c8d](https://github.com/auth0/node-jsonwebtoken/commit/44e3c8d757e6b4e2a57a69a035f26b4abec3e327) +- Fix wrong error message when the issuer doesn't match. [44e3c8d](https://github.com/auth0/node-jsonwebtoken/commit/44e3c8d757e6b4e2a57a69a035f26b4abec3e327) +- Fix wrong `iat` and `exp` values when signing with `noTimestamp`. [331b7bc](https://github.com/auth0/node-jsonwebtoken/commit/331b7bc9cc335561f8806f2c4558e105cb53e0a6)
@@ -0,0 +1,21 @@
+The MIT License (MIT) + +Copyright (c) 2015 Auth0, Inc. <support@auth0.com> (http://auth0.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.
@@ -0,0 +1,260 @@
+# jsonwebtoken [](http://travis-ci.org/auth0/node-jsonwebtoken)[](https://david-dm.org/auth0/node-jsonwebtoken) + + +An implementation of [JSON Web Tokens](https://tools.ietf.org/html/rfc7519). + +This was developed against `draft-ietf-oauth-json-web-token-08`. It makes use of [node-jws](https://github.com/brianloveswords/node-jws) + +# Install + +```bash +$ npm install jsonwebtoken +``` + +# Usage + +### jwt.sign(payload, secretOrPrivateKey, options, [callback]) + +(Asynchronous) If a callback is supplied, callback is called with the `err` or the JWT. + +(Synchronous) Returns the JsonWebToken as string + +`payload` could be an object literal, buffer or string. *Please note that* `exp` is only set if the payload is an object literal. + +`secretOrPrivateKey` is a string or buffer containing either the secret for HMAC algorithms, or the PEM +encoded private key for RSA and ECDSA. + +`options`: + +* `algorithm` (default: `HS256`) +* `expiresIn`: expressed in seconds or a string describing a time span [rauchg/ms](https://github.com/rauchg/ms.js). Eg: `60`, `"2 days"`, `"10h"`, `"7d"` +* `notBefore`: expressed in seconds or a string describing a time span [rauchg/ms](https://github.com/rauchg/ms.js). Eg: `60`, `"2 days"`, `"10h"`, `"7d"` +* `audience` +* `issuer` +* `jwtid` +* `subject` +* `noTimestamp` +* `header` + +If `payload` is not a buffer or a string, it will be coerced into a string using `JSON.stringify`. + +There are no default values for `expiresIn`, `notBefore`, `audience`, `subject`, `issuer`. These claims can also be provided in the payload directly with `exp`, `nbf`, `aud` and `sub` respectively, but you can't include in both places. + + +The header can be customized via the `option.header` object. + +Generated jwts will include an `iat` (issued at) claim by default unless `noTimestamp` is specified. If `iat` is inserted in the payload, it will be used instead of the real timestamp for calculating other things like `exp` given a timespan in `options.expiresIn`. + +Example + +```js +// sign with default (HMAC SHA256) +var jwt = require('jsonwebtoken'); +var token = jwt.sign({ foo: 'bar' }, 'shhhhh'); +//backdate a jwt 30 seconds +var older_token = jwt.sign({ foo: 'bar', iat: Math.floor(Date.now() / 1000) - 30 }, 'shhhhh'); + +// sign with RSA SHA256 +var cert = fs.readFileSync('private.key'); // get private key +var token = jwt.sign({ foo: 'bar' }, cert, { algorithm: 'RS256'}); + +// sign asynchronously +jwt.sign({ foo: 'bar' }, cert, { algorithm: 'RS256' }, function(err, token) { + console.log(token); +}); +``` + +### jwt.verify(token, secretOrPublicKey, [options, callback]) + +(Asynchronous) If a callback is supplied, function acts asynchronously. Callback passed the payload decoded if the signature (and optionally expiration, audience, issuer) are valid. If not, it will be passed the error. + +(Synchronous) If a callback is not supplied, function acts synchronously. Returns the payload decoded if the signature (and optionally expiration, audience, issuer) are valid. If not, it will throw the error. + +`token` is the JsonWebToken string + +`secretOrPublicKey` is a string or buffer containing either the secret for HMAC algorithms, or the PEM +encoded public key for RSA and ECDSA. + +`options` + +* `algorithms`: List of strings with the names of the allowed algorithms. For instance, `["HS256", "HS384"]`. +* `audience`: if you want to check audience (`aud`), provide a value here +* `issuer` (optional): string or array of strings of valid values for the `iss` field. +* `ignoreExpiration`: if `true` do not validate the expiration of the token. +* `ignoreNotBefore`... +* `subject`: if you want to check subject (`sub`), provide a value here +* `clockTolerance`: number of second to tolerate when checking the `nbf` and `exp` claims, to deal with small clock differences among different servers + + +```js +// verify a token symmetric - synchronous +var decoded = jwt.verify(token, 'shhhhh'); +console.log(decoded.foo) // bar + +// verify a token symmetric +jwt.verify(token, 'shhhhh', function(err, decoded) { + console.log(decoded.foo) // bar +}); + +// invalid token - synchronous +try { + var decoded = jwt.verify(token, 'wrong-secret'); +} catch(err) { + // err +} + +// invalid token +jwt.verify(token, 'wrong-secret', function(err, decoded) { + // err + // decoded undefined +}); + +// verify a token asymmetric +var cert = fs.readFileSync('public.pem'); // get public key +jwt.verify(token, cert, function(err, decoded) { + console.log(decoded.foo) // bar +}); + +// verify audience +var cert = fs.readFileSync('public.pem'); // get public key +jwt.verify(token, cert, { audience: 'urn:foo' }, function(err, decoded) { + // if audience mismatch, err == invalid audience +}); + +// verify issuer +var cert = fs.readFileSync('public.pem'); // get public key +jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer' }, function(err, decoded) { + // if issuer mismatch, err == invalid issuer +}); + +// verify jwt id +var cert = fs.readFileSync('public.pem'); // get public key +jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer', jwtid: 'jwtid' }, function(err, decoded) { + // if jwt id mismatch, err == invalid jwt id +}); + +// verify subject +var cert = fs.readFileSync('public.pem'); // get public key +jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer', jwtid: 'jwtid', subject: 'subject' }, function(err, decoded) { + // if subject mismatch, err == invalid subject +}); + +// alg mismatch +var cert = fs.readFileSync('public.pem'); // get public key +jwt.verify(token, cert, { algorithms: ['RS256'] }, function (err, payload) { + // if token alg != RS256, err == invalid signature +}); + +``` + +### jwt.decode(token [, options]) + +(Synchronous) Returns the decoded payload without verifying if the signature is valid. + +__Warning:__ This will __not__ verify whether the signature is valid. You should __not__ use this for untrusted messages. You most likely want to use `jwt.verify` instead. + +`token` is the JsonWebToken string + +`options`: + +* `json`: force JSON.parse on the payload even if the header doesn't contain `"typ":"JWT"`. +* `complete`: return an object with the decoded payload and header. + +Example + +```js +// get the decoded payload ignoring signature, no secretOrPrivateKey needed +var decoded = jwt.decode(token); + +// get the decoded payload and header +var decoded = jwt.decode(token, {complete: true}); +console.log(decoded.header); +console.log(decoded.payload) +``` + +## Errors & Codes +Possible thrown errors during verification. +Error is the first argument of the verification callback. + +### TokenExpiredError + +Thrown error if the token is expired. + +Error object: + +* name: 'TokenExpiredError' +* message: 'jwt expired' +* expiredAt: [ExpDate] + +```js +jwt.verify(token, 'shhhhh', function(err, decoded) { + if (err) { + /* + err = { + name: 'TokenExpiredError', + message: 'jwt expired', + expiredAt: 1408621000 + } + */ + } +}); +``` + +### JsonWebTokenError +Error object: + +* name: 'JsonWebTokenError' +* message: + * 'jwt malformed' + * 'jwt signature is required' + * 'invalid signature' + * 'jwt audience invalid. expected: [OPTIONS AUDIENCE]' + * 'jwt issuer invalid. expected: [OPTIONS ISSUER]' + * 'jwt id invalid. expected: [OPTIONS JWT ID]' + * 'jwt subject invalid. expected: [OPTIONS SUBJECT]' + +```js +jwt.verify(token, 'shhhhh', function(err, decoded) { + if (err) { + /* + err = { + name: 'JsonWebTokenError', + message: 'jwt malformed' + } + */ + } +}); +``` + +## Algorithms supported + +Array of supported algorithms. The following algorithms are currently supported. + +alg Parameter Value | Digital Signature or MAC Algorithm +----------------|---------------------------- +HS256 | HMAC using SHA-256 hash algorithm +HS384 | HMAC using SHA-384 hash algorithm +HS512 | HMAC using SHA-512 hash algorithm +RS256 | RSASSA using SHA-256 hash algorithm +RS384 | RSASSA using SHA-384 hash algorithm +RS512 | RSASSA using SHA-512 hash algorithm +ES256 | ECDSA using P-256 curve and SHA-256 hash algorithm +ES384 | ECDSA using P-384 curve and SHA-384 hash algorithm +ES512 | ECDSA using P-521 curve and SHA-512 hash algorithm +none | No digital signature or MAC value included + +# TODO + +* X.509 certificate chain is not checked + +## Issue Reporting + +If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues. + +## Author + +[Auth0](https://auth0.com) + +## License + +This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info.
@@ -0,0 +1,28 @@
+#!/usr/bin/env node + +var changelog = require('conventional-changelog'); +var semver_regex = /\bv?(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?\b/ig; + +const commitPartial = ` - {{header}} + +{{~!-- commit hash --}} {{#if @root.linkReferences}}([{{hash}}]({{#if @root.host}}{{@root.host}}/{{/if}}{{#if @root.owner}}{{@root.owner}}/{{/if}}{{@root.repository}}/{{@root.commit}}/{{hash}})){{else}}{{hash~}}{{/if}} + +{{~!-- commit references --}}{{#if references}}, closes{{~#each references}} {{#if @root.linkReferences}}[{{#if this.owner}}{{this.owner}}/{{/if}}{{this.repository}}#{{this.issue}}]({{#if @root.host}}{{@root.host}}/{{/if}}{{#if this.repository}}{{#if this.owner}}{{this.owner}}/{{/if}}{{this.repository}}{{else}}{{#if @root.owner}}{{@root.owner}}/{{/if}}{{@root.repository}}{{/if}}/{{@root.issue}}/{{this.issue}}){{else}}{{#if this.owner}}{{this.owner}}/{{/if}}{{this.repository}}#{{this.issue}}{{/if}}{{/each}}{{/if}} +`; + +const headerPartial = `## {{version}}{{#if title}} "{{title}}"{{/if}}{{#if date}} - {{date}}{{/if}} +`; + +changelog({ + releaseCount: 19, + // preset: 'jshint' +}, null, null, null, { + transform: function (commit) { + if (commit.header && semver_regex.exec(commit.header)) { + return null; + } + return commit; + }, + commitPartial: commitPartial, + headerPartial: headerPartial +}).pipe(process.stdout);
@@ -0,0 +1,30 @@
+var jws = require('jws'); + +module.exports = function (jwt, options) { + options = options || {}; + var decoded = jws.decode(jwt, options); + if (!decoded) { return null; } + var payload = decoded.payload; + + //try parse the payload + if(typeof payload === 'string') { + try { + var obj = JSON.parse(payload); + if(typeof obj === 'object') { + payload = obj; + } + } catch (e) { } + } + + //return header if `complete` option is enabled. header includes claims + //such as `kid` and `alg` used to select the key within a JWKS needed to + //verify the signature + if (options.complete === true) { + return { + header: decoded.header, + payload: payload, + signature: decoded.signature + }; + } + return payload; +};
@@ -0,0 +1,8 @@
+module.exports = { + decode: require('./decode'), + verify: require('./verify'), + sign: require('./sign'), + JsonWebTokenError: require('./lib/JsonWebTokenError'), + NotBeforeError: require('./lib/NotBeforeError'), + TokenExpiredError: require('./lib/TokenExpiredError'), +};
@@ -0,0 +1,12 @@
+var JsonWebTokenError = function (message, error) { + Error.call(this, message); + Error.captureStackTrace(this, this.constructor); + this.name = 'JsonWebTokenError'; + this.message = message; + if (error) this.inner = error; +}; + +JsonWebTokenError.prototype = Object.create(Error.prototype); +JsonWebTokenError.prototype.constructor = JsonWebTokenError; + +module.exports = JsonWebTokenError;
@@ -0,0 +1,13 @@
+var JsonWebTokenError = require('./JsonWebTokenError'); + +var NotBeforeError = function (message, date) { + JsonWebTokenError.call(this, message); + this.name = 'NotBeforeError'; + this.date = date; +}; + +NotBeforeError.prototype = Object.create(JsonWebTokenError.prototype); + +NotBeforeError.prototype.constructor = NotBeforeError; + +module.exports = NotBeforeError;
@@ -0,0 +1,13 @@
+var JsonWebTokenError = require('./JsonWebTokenError'); + +var TokenExpiredError = function (message, expiredAt) { + JsonWebTokenError.call(this, message); + this.name = 'TokenExpiredError'; + this.expiredAt = expiredAt; +}; + +TokenExpiredError.prototype = Object.create(JsonWebTokenError.prototype); + +TokenExpiredError.prototype.constructor = TokenExpiredError; + +module.exports = TokenExpiredError;
@@ -0,0 +1,18 @@
+var ms = require('ms'); + +module.exports = function (time, iat) { + var timestamp = iat || Math.floor(Date.now() / 1000); + + if (typeof time === 'string') { + var milliseconds = ms(time); + if (typeof milliseconds === 'undefined') { + return; + } + return Math.floor(timestamp + milliseconds / 1000); + } else if (typeof time === 'number') { + return timestamp + time; + } else { + return; + } + +};
@@ -0,0 +1,6 @@
+.PHONY: test + +MOCHA = ./node_modules/mocha/bin/mocha + +test: + $(MOCHA) -R list
@@ -0,0 +1,95 @@
+# cb() + +A minimal node.js utility for handling common (but often overlooked) callback scenarios. + +##Features + + * `.timeout()`: Simple callback timeouts + * `.error()`: Explicit error handling + * `.once()`: Once-and-only-once callback semantics + * Guaranteed asynchronous callback execution (protects against code that breaks this assumption) + +## Installation + + $ npm install cb + +## Usage + +### Basic Usage + +The most basic usage of `cb` consists of passing in your own function reference. In this example, `cb` will do nothing other +than insure the once-and-only-once, asynchronous invocation of the callback. + + doAsync(cb(function(err, res) { + console.log(res); + })); + +### Timeout Handling + +Timeouts are specified through the `.timeout()` method, and are specified in milliseconds. If a timeout does occur, the error +passed to the callback will be an instance of `cb.TimeoutError`. + + doReallySlowAsync(cb(function(err, res) { + assert(err instanceof cb.TimeoutError); + }).timeout(50)); + +*Note: once a timeout has occured, any tardy attempts to invoke the callback will be ignored.* + +### Explicit Error Handling + +In situations where it is convenient to separate the code that runs on success or failure, this can easily be accomplished +with `.error()`. If an 'errback' handler has been provided to `.error()`, then it is assumed that the error-first parameter +to the success handler is no longer required. To illustrate, + + doAsync(cb(function(err, res) { + if (err) { + console.error(err); + } else { + console.log(res); + } + })); + +Can be rewritten as: + + doAsync(cb(console.log).error(console.error)); + +### Force Once-and-only-once Callback Execution + +Sometimes it's necessary to ensure that a callback is invoked once, and no more. Once-and-only-once execution semantics can be +enforced by using `.once()`. + + function runTwice(callback) { + process.nextTick(function() { + callback(); + callback(); + }); + } + + runTwice(cb(function() { + console.log('I will only run once'); + }).once()); + +*Note: technically, `.once()` simply enforces at-most-once semantics. However, when combined with `.timeout()`, once-and-only-once +is achieved.* + +### Combining Features + +The `cb` API is fully chainable, and any arrangement of the features is valid. For example: + + doAsync(cb(console.log).error(console.error).timeout(50).once()); + +## Running the Tests + + $ make test + +## License + +The MIT License (MIT) + +Copyright (c) 2012 Jeremy Martin + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,39 @@
+module.exports = function(callback) { + + var cb = function() { + if (timedout || (once && count)) return; + count += 1; + tid && clearTimeout(tid); + + var args = Array.prototype.slice.call(arguments); + process.nextTick(function() { + if (!errback) return callback.apply(this, args); + args[0] ? errback(args[0]) : callback.apply(this, args.slice(1)); + }); + + }, count = 0, once = false, timedout = false, errback, tid; + + cb.timeout = function(ms) { + tid && clearTimeout(tid); + tid = setTimeout(function() { + cb(new TimeoutError(ms)); + timedout = true; + }, ms); + return cb; + }; + + cb.error = function(func) { errback = func; return cb; }; + + cb.once = function() { once = true; return cb; }; + + return cb; + +}; + +var TimeoutError = module.exports.TimeoutError = function TimeoutError(ms) { + this.message = 'Specified timeout of ' + ms + 'ms was reached'; + Error.captureStackTrace(this, this.constructor); +}; +TimeoutError.prototype = new Error; +TimeoutError.prototype.constructor = TimeoutError; +TimeoutError.prototype.name = 'TimeoutError';
@@ -0,0 +1,46 @@
+{ + "author": { + "name": "Jeremy Martin", + "email": "jmar777@gmail.com", + "url": "http://twitter.com/jmar777" + }, + "name": "cb", + "description": "Super simple callback mechanism with support for timeouts and explicit error handling", + "version": "0.1.0", + "repository": { + "type": "git", + "url": "git://github.com/jmar777/cb.git" + }, + "main": "lib/cb.js", + "devDependencies": { + "mocha": ">=0.3.6" + }, + "engines": { + "node": ">=0.6.0" + }, + "_npmUser": { + "name": "jmar777", + "email": "jmar777@gmail.com" + }, + "_id": "cb@0.1.0", + "dependencies": {}, + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.0-2", + "_nodeVersion": "v0.6.8", + "_defaultsLoaded": true, + "dist": { + "shasum": "26f7e740f2808facc83cef7b20392e4d881b5203", + "tarball": "https://registry.npmjs.org/cb/-/cb-0.1.0.tgz" + }, + "maintainers": [ + { + "name": "jmar777", + "email": "jmar777@gmail.com" + } + ], + "directories": {}, + "_shasum": "26f7e740f2808facc83cef7b20392e4d881b5203", + "_resolved": "https://registry.npmjs.org/cb/-/cb-0.1.0.tgz", + "_from": "cb@>=0.1.0 <0.2.0" +}
@@ -0,0 +1,125 @@
+var assert = require('assert'), + cb = require('../'); + +function invokeAsync(callback) { + setTimeout(function() { + callback(null, 'foo'); + }, 100); +} + +function invokeAsyncError(callback) { + setTimeout(function() { + callback(new Error()); + }, 100); +} + +function invokeAsyncTwice(callback) { + setTimeout(function() { + callback(null, 'foo'); + callback(null, 'foo'); + }, 100); +} + +describe('cb(callback)', function() { + + it('should invoke the provided callback', function(done) { + invokeAsync(cb(function(err, res) { + assert.strictEqual(res, 'foo'); + done(); + })); + }); + + it('shouldn\'t mess with errors', function(done) { + invokeAsyncError(cb(function(err, res) { + assert(err); + done(); + })); + }); + + it('should allow multiple executions', function(done) { + var count = 0; + invokeAsyncTwice(cb(function(err, res) { + count++; + if (count === 2) done(); + })); + }); + +}); + +describe('cb(callback).timeout(ms)', function() { + + it('should complete successfully within timeout period', function(done) { + invokeAsync(cb(function(err, res) { + assert.strictEqual(res, 'foo'); + done(); + }).timeout(200)); + }); + + it('should complete with an error after timeout period', function(done) { + invokeAsync(cb(function(err, res) { + assert(err); + done(); + }).timeout(50)); + }); + + it('error resulting from a timeout should be instanceof cb.TimeoutError', function(done) { + invokeAsync(cb(function(err, res) { + assert(err instanceof cb.TimeoutError); + done(); + }).timeout(50)); + }); + +}); + +describe('cb(callback).error(errback)', function() { + + it('should skip the err argument when invoking callback', function(done) { + invokeAsync(cb(function(res) { + assert.strictEqual(res, 'foo'); + done(); + }).error(assert.ifError)); + }); + + it('should pass errors to provided errback', function(done) { + invokeAsyncError(cb(function(res) { + throw new Error('should not be invoked'); + }).error(function(err) { + assert(err); + done(); + })); + }); + +}); + +describe('cb(callback).error(errback).timeout(ms)', function() { + + it('should skip the err argument when invoking callback', function(done) { + invokeAsync(cb(function(res) { + assert.strictEqual(res, 'foo'); + done(); + }).error(assert.ifError).timeout(200)); + }); + + it('should pass timeout error to provided errback', function(done) { + invokeAsyncError(cb(function(res) { + throw new Error('should not be invoked'); + }).error(function(err) { + assert(err); + done(); + }).timeout(50)); + }); + +}); + +describe('cb(callback).once()', function() { + + it('should allow multiple executions', function(done) { + var count = 0; + invokeAsyncTwice(cb(function(err, res) { + count++; + assert.notEqual(count, 2); + setTimeout(done, 100); + }).once()); + }); + +});
@@ -0,0 +1,21 @@
+.c9 +.idea +.project +*.iml +npm-debug.log +dump.rdb +node_modules +results.tap +results.xml +npm-shrinkwrap.json +config.json +.DS_Store +*/.DS_Store +*/*/.DS_Store +._* +*/._* +*/*/._* +coverage.* +lib-cov +complexity.md +sandbox.js
@@ -0,0 +1,9 @@
+language: node_js + +node_js: + - "0.10" + - "4.0" + - "4" + - "5" + +sudo: false
@@ -0,0 +1,1515 @@
+<!-- version --> +# 6.10.1 API Reference +<!-- versionstop --> + +<img src="https://raw.github.com/hapijs/joi/master/images/validation.png" align="right" /> + +<!-- toc --> + +- [Joi](#joi) + - [`validate(value, schema, [options], [callback])`](#validatevalue-schema-options-callback) + - [`compile(schema)`](#compileschema) + - [`assert(value, schema, [message])`](#assertvalue-schema-message) + - [`attempt(value, schema, [message])`](#attemptvalue-schema-message) + - [`isRef(ref)`](#isrefref) + - [`any`](#any) + - [`any.allow(value)`](#anyallowvalue) + - [`any.valid(value)` - aliases: `only`, `equal`](#anyvalidvalue---aliases-only-equal) + - [`any.invalid(value)` - aliases: `disallow`, `not`](#anyinvalidvalue---aliases-disallow-not) + - [`any.required()`](#anyrequired) + - [`any.optional()`](#anyoptional) + - [`any.forbidden()`](#anyforbidden) + - [`any.strip()`](#anystrip) + - [`any.description(desc)`](#anydescriptiondesc) + - [`any.notes(notes)`](#anynotesnotes) + - [`any.tags(tags)`](#anytagstags) + - [`any.meta(meta)`](#anymetameta) + - [`any.example(value)`](#anyexamplevalue) + - [`any.unit(name)`](#anyunitname) + - [`any.options(options)`](#anyoptionsoptions) + - [`any.strict(isStrict)`](#anystrictisstrict) + - [`any.default([value, [description]])`](#anydefaultvalue-description) + - [`any.concat(schema)`](#anyconcatschema) + - [`any.when(ref, options)`](#anywhenref-options) + - [`any.label(name)`](#anylabelname) + - [`any.raw(isRaw)`](#anyrawisraw) + - [`any.empty(schema)`](#anyemptyschema) + - [`array`](#array) + - [`array.sparse(enabled)`](#arraysparseenabled) + - [`array.single(enabled)`](#arraysingleenabled) + - [`array.items(type)`](#arrayitemstype) + - [`array.ordered(type)`](#arrayorderedtype) + - [`array.min(limit)`](#arrayminlimit) + - [`array.max(limit)`](#arraymaxlimit) + - [`array.length(limit)`](#arraylengthlimit) + - [`array.unique()`](#arrayunique) + - [`boolean`](#boolean) + - [`binary`](#binary) + - [`binary.encoding(encoding)`](#binaryencodingencoding) + - [`binary.min(limit)`](#binaryminlimit) + - [`binary.max(limit)`](#binarymaxlimit) + - [`binary.length(limit)`](#binarylengthlimit) + - [`date`](#date) + - [`date.min(date)`](#datemindate) + - [`date.max(date)`](#datemaxdate) + - [`date.format(format)`](#dateformatformat) + - [`date.iso()`](#dateiso) + - [`func`](#func) + - [`number`](#number) + - [`number.min(limit)`](#numberminlimit) + - [`number.max(limit)`](#numbermaxlimit) + - [`number.greater(limit)`](#numbergreaterlimit) + - [`number.less(limit)`](#numberlesslimit) + - [`number.integer()`](#numberinteger) + - [`number.precision(limit)`](#numberprecisionlimit) + - [`number.multiple(base)`](#numbermultiplebase) + - [`number.positive()`](#numberpositive) + - [`number.negative()`](#numbernegative) + - [`object`](#object) + - [`object.keys([schema])`](#objectkeysschema) + - [`{} notation`](#-notation) + - [`Joi.object([schema]) notation`](#joiobjectschema-notation) + - [`Joi.object().keys([schema]) notation`](#joiobjectkeysschema-notation) + - [`object.min(limit)`](#objectminlimit) + - [`object.max(limit)`](#objectmaxlimit) + - [`object.length(limit)`](#objectlengthlimit) + - [`object.pattern(regex, schema)`](#objectpatternregex-schema) + - [`object.and(peers)`](#objectandpeers) + - [`object.nand(peers)`](#objectnandpeers) + - [`object.or(peers)`](#objectorpeers) + - [`object.xor(peers)`](#objectxorpeers) + - [`object.with(key, peers)`](#objectwithkey-peers) + - [`object.without(key, peers)`](#objectwithoutkey-peers) + - [`object.rename(from, to, [options])`](#objectrenamefrom-to-options) + - [`object.assert(ref, schema, [message])`](#objectassertref-schema-message) + - [`object.unknown([allow])`](#objectunknownallow) + - [`object.type(constructor, [name])`](#objecttypeconstructor-name) + - [`object.requiredKeys(children)`](#objectrequiredkeyschildren) + - [`object.optionalKeys(children)`](#objectoptionalkeyschildren) + - [`string`](#string) + - [`string.insensitive()`](#stringinsensitive) + - [`string.min(limit, [encoding])`](#stringminlimit-encoding) + - [`string.max(limit, [encoding])`](#stringmaxlimit-encoding) + - [`string.creditCard()`](#stringcreditcard) + - [`string.length(limit, [encoding])`](#stringlengthlimit-encoding) + - [`string.regex(pattern, [name])`](#stringregexpattern-name) + - [`string.replace(pattern, replacement)`](#stringreplacepattern-replacement) + - [`string.alphanum()`](#stringalphanum) + - [`string.token()`](#stringtoken) + - [`string.email([options])`](#stringemailoptions) + - [`string.ip([options])`](#stringipoptions) + - [`string.uri([options])`](#stringurioptions) + - [`string.guid()`](#stringguid) + - [`string.hex()`](#stringhex) + - [`string.hostname()`](#stringhostname) + - [`string.lowercase()`](#stringlowercase) + - [`string.uppercase()`](#stringuppercase) + - [`string.trim()`](#stringtrim) + - [`string.isoDate()`](#stringisodate) + - [`alternatives`](#alternatives) + - [`alternatives.try(schemas)`](#alternativestryschemas) + - [`alternatives.when(ref, options)`](#alternativeswhenref-options) + - [`ref(key, [options])`](#refkey-options) +- [Errors](#errors) + +<!-- tocstop --> + +## Joi + +### `validate(value, schema, [options], [callback])` + +Validates a value using the given schema and options where: +- `value` - the value being validated. +- `schema` - the validation schema. Can be a **joi** type object or a plain object where every key is assigned a **joi** type object. +- `options` - an optional object with the following optional keys: + - `abortEarly` - when `true`, stops validation on the first error, otherwise returns all the errors found. Defaults to `true`. + - `convert` - when `true`, attempts to cast values to the required types (e.g. a string to a number). Defaults to `true`. + - `allowUnknown` - when `true`, allows object to contain unknown keys which are ignored. Defaults to `false`. + - `skipFunctions` - when `true`, ignores unknown keys with a function value. Defaults to `false`. + - `stripUnknown` - when `true`, unknown keys are deleted (only when value is an object or an array). Defaults to `false`. + - `language` - overrides individual error messages, when `'label'` is set, it overrides the key name in the error message. Defaults to no override (`{}`). + - `presence` - sets the default presence requirements. Supported modes: `'optional'`, `'required'`, and `'forbidden'`. + Defaults to `'optional'`. + - `context` - provides an external data set to be used in [references](#refkey-options). Can only be set as an external option to + `validate()` and not using `any.options()`. + - `noDefaults` - when `true`, do not apply default values. Defaults to `false`. +- `callback` - the optional synchronous callback method using the signature `function(err, value)` where: + - `err` - if validation failed, the [error](#errors) reason, otherwise `null`. + - `value` - the validated value with any type conversions and other modifiers applied (the input is left unchanged). `value` can be + incomplete if validation failed and `abortEarly` is `true`. If callback is not provided, then returns an object with [error](#errors) + and value properties. + +```javascript +var schema = { + a: Joi.number() +}; + +var value = { + a: '123' +}; + +Joi.validate(value, schema, function (err, value) { }); +// err -> null +// value.a -> 123 (number, not string) + +// or +var result = Joi.validate(value, schema); +// result.error -> null +// result.value -> { "a" : 123 } +``` + +### `compile(schema)` + +Converts literal schema definition to **joi** schema object (or returns the same back if already a **joi** schema object) where: +- `schema` - the schema definition to compile. + +```javascript +var definition = ['key', 5, { a: true, b: [/^a/, 'boom'] }]; +var schema = Joi.compile(definition); + +// Same as: + +var schema = Joi.alternatives().try([ + Joi.string().valid('key'), + Joi.number().valid(5), + Joi.object().keys({ + a: Joi.boolean().valid(true), + b: Joi.alternatives().try([ + Joi.string().regex(/^a/), + Joi.string().valid('boom') + ]) + }) +]); +``` + +### `assert(value, schema, [message])` + +Validates a value against a schema and [throws](#errors) if validation fails where: +- `value` - the value to validate. +- `schema` - the schema object. +- `message` - optional message string prefix added in front of the error message. may also be an Error object. + +```javascript +Joi.assert('x', Joi.number()); +``` + +### `attempt(value, schema, [message])` + +Validates a value against a schema, returns valid object, and [throws](#errors) if validation fails where: +- `value` - the value to validate. +- `schema` - the schema object. +- `message` - optional message string prefix added in front of the error message. may also be an Error object. + +```javascript +Joi.attempt('x', Joi.number()); // throws error +var result = Joi.attempt('4', Joi.number()); // result -> 4 +``` + +### `isRef(ref)` + +Checks whether or not the provided argument is a reference. +It's especially useful if you want to post-process error messages. + +```js +var ref = Joi.ref('a'); +Joi.isRef(ref); // returns true +``` + +### `any` + +Generates a schema object that matches any data type. + +```javascript +var any = Joi.any(); +any.validate('a', function (err, value) { }); +``` + +#### `any.allow(value)` + +Whitelists a value where: +- `value` - the allowed value which can be of any type and will be matched against the validated value before applying any other rules. + `value` can be an array of values, or multiple values can be passed as individual arguments. `value` supports [references](#refkey-options). + +Note that this whitelist of allowed values is in *addition* to any other permitted values. +To create an exclusive whitelist of values, see [`any.valid(value)`](#anyvalidvalue). + +```javascript +var schema = { + a: Joi.any().allow('a'), + b: Joi.any().allow('b', 'B'), + c: Joi.any().allow(['c', 'C']) +}; +``` + +#### `any.valid(value)` - aliases: `only`, `equal` + +Adds the provided values into the allowed whitelist and marks them as the only valid values allowed where: +- `value` - the allowed value which can be of any type and will be matched against the validated value before applying any other rules. + `value` can be an array of values, or multiple values can be passed as individual arguments. `value` supports [references](#refkey-options). + +```javascript +var schema = { + a: Joi.any().valid('a'), + b: Joi.any().valid('b', 'B'), + c: Joi.any().valid(['c', 'C']) +}; +``` + +#### `any.invalid(value)` - aliases: `disallow`, `not` + +Blacklists a value where: +- `value` - the forbidden value which can be of any type and will be matched against the validated value before applying any other rules. + `value` can be an array of values, or multiple values can be passed as individual arguments. `value` supports [references](#refkey-options). + +```javascript +var schema = { + a: Joi.any().invalid('a'), + b: Joi.any().invalid('b', 'B'), + c: Joi.any().invalid(['c', 'C']) +}; +``` + +#### `any.required()` + +Marks a key as required which will not allow `undefined` as value. All keys are optional by default. + +```javascript +var schema = Joi.any().required(); +``` + +#### `any.optional()` + +Marks a key as optional which will allow `undefined` as values. Used to annotate the schema for readability as all keys are optional by default. + +```javascript +var schema = Joi.any().optional(); +``` + +#### `any.forbidden()` + +Marks a key as forbidden which will not allow any value except `undefined`. Used to explicitly forbid keys. + +```javascript +var schema = { + a: Joi.any().forbidden() +}; +``` + +#### `any.strip()` + +Marks a key to be removed from a resulting object or array after validation. Used to sanitize output. + +```javascript +var schema = { + username: Joi.string(), + password: Joi.string().strip() +}; + +schema.validate({ username: 'test', password: 'hunter2' }, function (err, value) { + // value = { username: 'test' } +}); + +var schema = Joi.array().items(Joi.string(), Joi.any().strip()); + +schema.validate(['one', 'two', true, false, 1, 2], function (err, value) { + // value = ['one', 'two'] +}); +``` + +#### `any.description(desc)` + +Annotates the key where: +- `desc` - the description string. + +```javascript +var schema = Joi.any().description('this key will match anything you give it'); +``` + +#### `any.notes(notes)` + +Annotates the key where: +- `notes` - the notes string or array of strings. + +```javascript +var schema = Joi.any().notes(['this is special', 'this is important']); +``` + +#### `any.tags(tags)` + +Annotates the key where: +- `tags` - the tag string or array of strings. + +```javascript +var schema = Joi.any().tags(['api', 'user']); +``` + +#### `any.meta(meta)` + +Attaches metadata to the key where: +- `meta` - the meta object to attach. + +```javascript +var schema = Joi.any().meta({ index: true }); +``` + +#### `any.example(value)` + +Annotates the key where: +- `value` - an example value. + +If the example fails to pass validation, the function will throw. + +```javascript +var schema = Joi.string().min(4).example('abcd'); +``` + +#### `any.unit(name)` + +Annotates the key where: +- `name` - the unit name of the value. + +```javascript +var schema = Joi.number().unit('milliseconds'); +``` + +#### `any.options(options)` + +Overrides the global `validate()` options for the current key and any sub-key where: +- `options` - an object with the same optional keys as [`Joi.validate(value, schema, options, callback)`](#validatevalue-schema-options-callback). + +```javascript +var schema = Joi.any().options({ convert: false }); +``` + +#### `any.strict(isStrict)` + +Strict mode sets the `options.convert` options to `false` which prevent type casting for the current key and any child keys. +- `isStrict` - whether strict mode is enabled or not. Defaults to true. + +```javascript +var schema = Joi.any().strict(); +``` + +#### `any.default([value, [description]])` + +Sets a default value if the original value is undefined where: +- `value` - the value. + - `value` supports [references](#refkey-options). + - `value` may also be a function which returns the default value. If `value` is specified as a function that accepts a single parameter, that parameter will be a context object that can be used to derive the resulting value. **This clones the object however, which incurs some overhead so if you don't need access to the context define your method so that it does not accept any parameters**. + - without any `value`, `default` has no effect, except for `object` that will then create nested defaults (applying inner defaults of that object). + +Note that if `value` is an object, any changes to the object after `default()` is called will change the reference +and any future assignment. + +Additionally, when specifying a method you must either have a `description` property on your method or the second parameter is required. + +```javascript +var generateUsername = function (context) { + + return context.firstname.toLowerCase() + '-' + context.lastname.toLowerCase(); +}; +generateUsername.description = 'generated username'; + +var schema = { + username: Joi.string().default(generateUsername), + firstname: Joi.string(), + lastname: Joi.string(), + created: Joi.date().default(Date.now, 'time of creation'), + status: Joi.string().default('registered') +}; + +Joi.validate({ + firstname: 'Jane', + lastname: 'Doe' +}, schema, function (err, value) { + + // value.status === 'registered' + // value.username === 'jane-doe' + // value.created will be the time of validation +}); +``` + +#### `any.concat(schema)` + +Returns a new type that is the result of adding the rules of one type to another where: +- `schema` - a **joi** type to merge into the current schema. Can only be of the same type as the context type or `any`. If applied to an `any` type, the schema can be any other schema. + +```javascript +var a = Joi.string().valid('a'); +var b = Joi.string().valid('b'); +var ab = a.concat(b); +``` + +#### `any.when(ref, options)` + +Converts the type into an [`alternatives`](#alternatives) type where the conditions are merged into the type definition where: +- `ref` - the key name or [reference](#refkey-options). +- `options` - an object with: + - `is` - the required condition **joi** type. + - `then` - the alternative schema type if the condition is true. Required if `otherwise` is missing. + - `otherwise` - the alternative schema type if the condition is false. Required if `then` is missing. + +```javascript +var schema = { + a: Joi.any().valid('x').when('b', { is: 5, then: Joi.valid('y'), otherwise: Joi.valid('z') }), + b: Joi.any() +}; +``` + +Alternatively, if you want to specify a specific type such as `string`, `array`, etc, you can do so like this: + +```javascript +var schema = { + a: Joi.valid('a', 'b', 'other'), + other: Joi.string() + .when('a', { is: 'other', then: Joi.required() }), +}; +``` + +#### `any.label(name)` + +Overrides the key name in error messages. +- `name` - the name of the key. + +```javascript +var schema = { + first_name: Joi.string().label('First Name') +}; +``` + +#### `any.raw(isRaw)` + +Outputs the original untouched value instead of the casted value. +- `isRaw` - whether to enable raw mode or not. Defaults to true. + +```javascript +var schema = { + timestamp: Joi.date().format('YYYYMMDD').raw() +}; +``` + +#### `any.empty(schema)` + +Considers anything that matches the schema to be empty (`undefined`). +- `schema` - any object or joi schema to match. An undefined schema unsets that rule. + +```js +var schema = Joi.string().empty(''); +schema.validate(''); // returns { error: null, value: undefined } +schema = schema.empty(); +schema.validate(''); // returns { error: "value" is not allowed to be empty, value: '' } +``` + +### `array` + +Generates a schema object that matches an array data type. Note that undefined values inside arrays are not allowed by default but can be by using `sparse()`. + +Supports the same methods of the [`any()`](#any) type. + +```javascript +var array = Joi.array().items(Joi.string().valid('a', 'b')); +array.validate(['a', 'b', 'a'], function (err, value) { }); +``` + +#### `array.sparse(enabled)` + +Allow this array to be sparse. `enabled` can be used with a falsy value to go back to the default behavior. + +```javascript +var schema = Joi.array().sparse(); // undefined values are now allowed +schema = schema.sparse(false); // undefined values are now denied +``` + +#### `array.single(enabled)` + +Allow single values to be checked against rules as if it were provided as an array. + +`enabled` can be used with a falsy value to go back to the default behavior. + +```javascript +var schema = Joi.array().items(Joi.number()).single(); +schema.validate([4]); // returns `{ error: null, value: [ 4 ] }` +schema.validate(4); // returns `{ error: null, value: [ 4 ] }` +``` + +#### `array.items(type)` + +List the types allowed for the array values where: +- `type` - a **joi** schema object to validate each array item against. `type` can be an array of values, or multiple values can be passed as individual arguments. + +If a given type is `.required()` then there must be a matching item in the array. +If a type is `.forbidden()` then it cannot appear in the array. +Required items can be added multiple times to signify that multiple items must be found. +Errors will contain the number of items that didn't match. Any unmatched item having a [label](#anylabelname) will be mentioned explicitly. + +```javascript +var schema = Joi.array().items(Joi.string(), Joi.number()); // array may contain strings and numbers +var schema = Joi.array().items(Joi.string().required(), Joi.string().required()); // array must contain at least two strings +var schema = Joi.array().items(Joi.string().valid('not allowed').forbidden(), Joi.string()); // array may contain strings, but none of those strings can match 'not allowed' +var schema = Joi.array().items(Joi.string().label('My string').required(), Joi.number().required()); // If this fails it can result in `[ValidationError: "value" does not contain [My string] and 1 other required value(s)]` +``` + +#### `array.ordered(type)` + +List the types in sequence order for the array values where: +- `type` - a **joi** schema object to validate against each array item in sequence order. `type` can be an array of values, or multiple values can be passed as individual arguments. + +If a given type is `.required()` then there must be a matching item with the same index position in the array. +Errors will contain the number of items that didn't match. Any unmatched item having a [label](#anylabelname) will be mentioned explicitly. + +```javascript +var schema = Joi.array().ordered(Joi.string().required(), Joi.number().required()); // array must have first item as string and second item as number +var schema = Joi.array().ordered(Joi.string().required()).items(Joi.number().required()); // array must have first item as string and 1 or more subsequent items as number +var schema = Joi.array().ordered(Joi.string().required(), Joi.number()); // array must have first item as string and optionally second item as number +``` + +#### `array.min(limit)` + +Specifies the minimum number of items in the array where: +- `limit` - the lowest number of array items allowed. + +```javascript +var schema = Joi.array().min(2); +``` + +#### `array.max(limit)` + +Specifies the maximum number of items in the array where: +- `limit` - the highest number of array items allowed. + +```javascript +var schema = Joi.array().max(10); +``` + +#### `array.length(limit)` + +Specifies the exact number of items in the array where: +- `limit` - the number of array items allowed. + +```javascript +var schema = Joi.array().length(5); +``` + +#### `array.unique()` + +Requires the array values to be unique. + +Be aware that a deep equality is performed on elements of the array having a type of `object`, a performance penalty is to be expected for this kind of operation. + +```javascript +var schema = Joi.array().unique(); +``` + +### `boolean` + +Generates a schema object that matches a boolean data type (as well as the strings 'true', 'false', 'yes', 'no', 'on' or 'off'). Can also be called via `bool()`. + +Supports the same methods of the [`any()`](#any) type. + +```javascript +var boolean = Joi.boolean(); +boolean.validate(true, function (err, value) { }); +``` + +### `binary` + +Generates a schema object that matches a Buffer data type (as well as the strings which will be converted to Buffers). + +Supports the same methods of the [`any()`](#any) type. + +```javascript +var schema = Joi.binary(); +``` + +#### `binary.encoding(encoding)` + +Sets the string encoding format if a string input is converted to a buffer where: +- `encoding` - the encoding scheme. + +```javascript +var schema = Joi.binary().encoding('base64'); +``` + +#### `binary.min(limit)` + +Specifies the minimum length of the buffer where: +- `limit` - the lowest size of the buffer. + +```javascript +var schema = Joi.binary().min(2); +``` + +#### `binary.max(limit)` + +Specifies the maximum length of the buffer where: +- `limit` - the highest size of the buffer. + +```javascript +var schema = Joi.binary().max(10); +``` + +#### `binary.length(limit)` + +Specifies the exact length of the buffer: +- `limit` - the size of buffer allowed. + +```javascript +var schema = Joi.binary().length(5); +``` + +### `date` + +Generates a schema object that matches a date type (as well as a JavaScript date string or number of milliseconds). + +Supports the same methods of the [`any()`](#any) type. + +```javascript +var date = Joi.date(); +date.validate('12-21-2012', function (err, value) { }); +``` + +#### `date.min(date)` + +Specifies the oldest date allowed where: +- `date` - the oldest date allowed. + +```javascript +var schema = Joi.date().min('1-1-1974'); +``` + +Notes: `'now'` can be passed in lieu of `date` so as to always compare relatively to the current date, allowing to explicitly ensure a date is either in the past or in the future. + +```javascript +var schema = Joi.date().min('now'); +``` + +It can also be a reference to another field. + +```javascript +var schema = Joi.object({ + from: Joi.date().required(), + to: Joi.date().min(Joi.ref('from')).required() +}); +``` + +#### `date.max(date)` + +Specifies the latest date allowed where: +- `date` - the latest date allowed. + +```javascript +var schema = Joi.date().max('12-31-2020'); +``` + +Notes: `'now'` can be passed in lieu of `date` so as to always compare relatively to the current date, allowing to explicitly ensure a date is either in the past or in the future. + +```javascript +var schema = Joi.date().max('now'); +``` + +It can also be a reference to another field. + +```javascript +var schema = Joi.object({ + from: Joi.date().max(Joi.ref('to')).required(), + to: Joi.date().required() +}); +``` + +#### `date.format(format)` + +Specifies the allowed date format: +- `format` - string or array of strings that follow the `moment.js` [format](http://momentjs.com/docs/#/parsing/string-format/). + +```javascript +var schema = Joi.date().format('YYYY/MM/DD'); +``` + +#### `date.iso()` + +Requires the string value to be in valid ISO 8601 date format. + +```javascript +var schema = Joi.date().iso(); +``` + +### `func` + +Generates a schema object that matches a function type. + +Supports the same methods of the [`object()`](#object) type. Note that validating a function keys will cause the function +to be cloned. While the function will retain its prototype and closure, it will lose its `length` property value (will be +set to `0`). + +```javascript +var func = Joi.func(); +func.validate(function () {}, function (err, value) { }); +``` + +### `number` + +Generates a schema object that matches a number data type (as well as strings that can be converted to numbers). + +`Infinity` and `-Infinity` are invalid by default, you can change that behavior by calling `allow(Infinity, -Infinity)`. + +Supports the same methods of the [`any()`](#any) type. + +```javascript +var number = Joi.number(); +number.validate(5, function (err, value) { }); +``` + +#### `number.min(limit)` + +Specifies the minimum value where: +- `limit` - the minimum value allowed. + +```javascript +var schema = Joi.number().min(2); +``` + +It can also be a reference to another field. + +```javascript +var schema = Joi.object({ + min: Joi.number().required(), + max: Joi.number().min(Joi.ref('min')).required() +}); +``` + +#### `number.max(limit)` + +Specifies the maximum value where: +- `limit` - the maximum value allowed. + +```javascript +var schema = Joi.number().max(10); +``` + +It can also be a reference to another field. + +```javascript +var schema = Joi.object({ + min: Joi.number().max(Joi.ref('max')).required(), + max: Joi.number().required() +}); +``` + +#### `number.greater(limit)` + +Specifies that the value must be greater than `limit`. + +```javascript +var schema = Joi.number().greater(5); +``` + +```javascript +var schema = Joi.object({ + min: Joi.number().required(), + max: Joi.number().greater(Joi.ref('min')).required() +}); +``` + +#### `number.less(limit)` + +Specifies that the value must be less than `limit`. + +```javascript +var schema = Joi.number().less(10); +``` + +It can also be a reference to another field. + +```javascript +var schema = Joi.object({ + min: Joi.number().less(Joi.ref('max')).required(), + max: Joi.number().required() +}); +``` + +#### `number.integer()` + +Requires the number to be an integer (no floating point). + +```javascript +var schema = Joi.number().integer(); +``` + +#### `number.precision(limit)` + +Specifies the maximum number of decimal places where: +- `limit` - the maximum number of decimal places allowed. + +```javascript +var schema = Joi.number().precision(2); +``` + +#### `number.multiple(base)` + +Specifies that the value must be a multiple of `base`: + +```javascript +var schema = Joi.number().multiple(3); +``` + +#### `number.positive()` + +Requires the number to be positive. + +```javascript +var schema = Joi.number().positive(); +``` + +#### `number.negative()` + +Requires the number to be negative. + +```javascript +var schema = Joi.number().negative(); +``` + +### `object` + +Generates a schema object that matches an object data type (as well as JSON strings that parsed into objects). Defaults +to allowing any child key. + +Supports the same methods of the [`any()`](#any) type. + +```javascript +var object = Joi.object().keys({ + a: Joi.number().min(1).max(10).integer(), + b: 'some string' +}); + +object.validate({ a: 5 }, function (err, value) { }); +``` + +#### `object.keys([schema])` + +Sets or extends the allowed object keys where: +- `schema` - optional object where each key is assigned a **joi** type object. If `schema` is `{}` no keys allowed. + If `schema` is `null` or `undefined`, any key allowed. If `schema` is an object with keys, the keys are added to any + previously defined keys (but narrows the selection if all keys previously allowed). Defaults to 'undefined' which + allows any child key. + +```javascript +var base = Joi.object().keys({ + a: Joi.number(), + b: Joi.string() +}); +// Validate keys a, b and c. +var extended = base.keys({ + c: Joi.boolean() +}); +``` + +Notes: We have three different ways to define a schema for performing a validation + +- Using the plain JS object notation: +```javascript +var schema = { + a: Joi.string(), + b: Joi.number() +}; +``` +- Using the `Joi.object([schema])` notation +```javascript +var schema = Joi.object({ + a: Joi.string(), + b: Joi.number() +}); +``` +- Using the `Joi.object().keys([schema])` notation +```javascript +var schema = Joi.object().keys({ + a: Joi.string(), + b: Joi.number() +}); +``` + +While all these three objects defined above will result in the same validation object, there are some differences in using one or another: + +##### `{} notation` + +When using the `{}` notation, you are just defining a plain JS object, which isn't a schema object. +You can pass it to the validation method but you can't call `validate()` method of the object because it's just a plain JS object. + +Besides, passing the `{}` object to the `validate()` method each time, will perform an expensive schema compilation operation on every validation. + +##### `Joi.object([schema]) notation` + +Using `Joi.object([schema])` will return a schema object, so you can call the `validate()` method directly, e.g: + +```javascript +var schema = Joi.object({ + a: Joi.boolean() +}); + +schema.validate(true, function (err, value) { + console.log('err: ', err); +}); +``` + +When you use `Joi.object([schema])`, it gets compiled the first time, so you can pass it to the `validate()` method multiple times and no overhead is added. + +Another benefits of using `Joi.object([schema])` instead of a plain JS object is that you can set any options on the object like allowing unknown keys, e.g: + +```javascript +var schema = Joi.object({ + arg: Joi.string().valid('firstname', 'lastname', 'title', 'company', 'jobtitle'), + value: Joi.string(), +}).pattern(/firstname|lastname/, Joi.string().min(2)); +``` + +##### `Joi.object().keys([schema]) notation` + +This is basically the same as `Joi.object([schema])`, but using `Joi.object().keys([schema])` is more useful when you want to add more keys (e.g. call `keys()` multiple times). If you are only adding one set of keys, you can skip the `keys()` method and just use `object()` directly. + +Some people like to use `keys()` to make the code more explicit (this is style only). + + +#### `object.min(limit)` + +Specifies the minimum number of keys in the object where: +- `limit` - the lowest number of keys allowed. + +```javascript +var schema = Joi.object().min(2); +``` + +#### `object.max(limit)` + +Specifies the maximum number of keys in the object where: +- `limit` - the highest number of object keys allowed. + +```javascript +var schema = Joi.object().max(10); +``` + +#### `object.length(limit)` + +Specifies the exact number of keys in the object where: +- `limit` - the number of object keys allowed. + +```javascript +var schema = Joi.object().length(5); +``` + +#### `object.pattern(regex, schema)` + +Specify validation rules for unknown keys matching a pattern where: +- `regex` - a regular expression tested against the unknown key names. +- `schema` - the schema object matching keys much validate against. + +```javascrip +var schema = Joi.object({ + a: Joi.string() +}).pattern(/\w\d/, Joi.boolean()); +``` + +#### `object.and(peers)` + +Defines an all-or-nothing relationship between keys where if one of the peers is present, all of them are required as +well where: +- `peers` - the key names of which if one present, all are required. `peers` can be a single string value, an + array of string values, or each peer provided as an argument. + +```javascript +var schema = Joi.object().keys({ + a: Joi.any(), + b: Joi.any() +}).and('a', 'b'); +``` + +#### `object.nand(peers)` + +Defines a relationship between keys where not all peers can be present at the +same time where: +- `peers` - the key names of which if one present, the others may not all be present. `peers` can be a single string value, an + array of string values, or each peer provided as an argument. + +```javascript +var schema = Joi.object().keys({ + a: Joi.any(), + b: Joi.any() +}).nand('a', 'b'); +``` + +#### `object.or(peers)` + +Defines a relationship between keys where one of the peers is required (and more than one is allowed) where: +- `peers` - the key names of which at least one must appear. `peers` can be a single string value, an + array of string values, or each peer provided as an argument. + +```javascript +var schema = Joi.object().keys({ + a: Joi.any(), + b: Joi.any() +}).or('a', 'b'); +``` + +#### `object.xor(peers)` + +Defines an exclusive relationship between a set of keys where one of them is required but not at the same time where: +- `peers` - the exclusive key names that must not appear together but where one of them is required. `peers` can be a single string value, an + array of string values, or each peer provided as an argument. + +```javascript +var schema = Joi.object().keys({ + a: Joi.any(), + b: Joi.any() +}).xor('a', 'b'); +``` + +#### `object.with(key, peers)` + +Requires the presence of other keys whenever the specified key is present where: +- `key` - the reference key. +- `peers` - the required peer key names that must appear together with `key`. `peers` can be a single string value or an array of string values. + +Note that unlike [`object.and()`](#objectandpeers), `with()` creates a dependency only between the `key` and each of the `peers`, not +between the `peers` themselves. + +```javascript +var schema = Joi.object().keys({ + a: Joi.any(), + b: Joi.any() +}).with('a', 'b'); +``` + +#### `object.without(key, peers)` + +Forbids the presence of other keys whenever the specified is present where: +- `key` - the reference key. +- `peers` - the forbidden peer key names that must not appear together with `key`. `peers` can be a single string value or an array of string values. + +```javascript +var schema = Joi.object().keys({ + a: Joi.any(), + b: Joi.any() +}).without('a', ['b']); +``` + +#### `object.rename(from, to, [options])` + +Renames a key to another name (deletes the renamed key) where: +- `from` - the original key name. +- `to` - the new key name. +- `options` - an optional object with the following optional keys: + - `alias` - if `true`, does not delete the old key name, keeping both the new and old keys in place. Defaults to `false`. + - `multiple` - if `true`, allows renaming multiple keys to the same destination where the last rename wins. Defaults to `false`. + - `override` - if `true`, allows renaming a key over an existing key. Defaults to `false`. + - `ignoreUndefined` - if `true`, skip renaming of a key if it's undefined. Defaults to `false`. + +Keys are renamed before any other validation rules are applied. + +```javascript +var object = Joi.object().keys({ + a: Joi.number() +}).rename('b', 'a'); + +object.validate({ b: 5 }, function (err, value) { }); +``` + +#### `object.assert(ref, schema, [message])` + +Verifies an assertion where: +- `ref` - the key name or [reference](#refkey-options). +- `schema` - the validation rules required to satisfy the assertion. If the `schema` includes references, they are resolved against + the object value, not the value of the `ref` target. +- `message` - optional human-readable message used when the assertion fails. Defaults to 'failed to pass the assertion test'. + +```javascript +var schema = Joi.object().keys({ + a: { + b: Joi.string(), + c: Joi.number() + }, + d: { + e: Joi.any() + } +}).assert('d.e', Joi.ref('a.c'), 'equal to a.c'); +``` + +#### `object.unknown([allow])` + +Overrides the handling of unknown keys for the scope of the current object only (does not apply to children) where: +- `allow` - if `false`, unknown keys are not allowed, otherwise unknown keys are ignored. + +```javascript +var schema = Joi.object({ a: Joi.any() }).unknown(); +``` + +#### `object.type(constructor, [name])` + +Requires the object to be an instance of a given constructor where: +- `constructor` - the constructor function that the object must be an instance of. +- `name` - an alternate name to use in validation errors. This is useful when the constructor function does not have a name. + +```javascript +var schema = Joi.object().type(RegExp); +``` + +#### `object.requiredKeys(children)` + +Sets the specified children to required. +- `children` - can be a single string value, an array of string values, or each child provided as an argument. + +```javascript +var schema = Joi.object().keys({ a: { b: Joi.number() }, c: { d: Joi.string() } }); +var requiredSchema = schema.requiredKeys('', 'a.b', 'c', 'c.d'); +``` + +Note that in this example `''` means the current object, `a` is not required but `b` is, as well as `c` and `d`. + +#### `object.optionalKeys(children)` + +Sets the specified children to optional. +- `children` - can be a single string value, an array of string values, or each child provided as an argument. + +```javascript +var schema = Joi.object().keys({ a: { b: Joi.number().required() }, c: { d: Joi.string().required() } }); +var requiredSchema = schema.optionalKeys('a.b', 'c.d'); +``` + +The behavior is exactly the same as `requiredKeys`. + +### `string` + +Generates a schema object that matches a string data type. Note that empty strings are not allowed by default and must be enabled with `allow('')`. + +Supports the same methods of the [`any()`](#any) type. + +```javascript +var schema = Joi.string().min(1).max(10); +schema.validate('12345', function (err, value) { }); +``` + +#### `string.insensitive()` + +Allows the value to match any whitelist of blacklist item in a case insensitive comparison. + +```javascript +var schema = Joi.string().valid('a').insensitive(); +``` + +#### `string.min(limit, [encoding])` + +Specifies the minimum number string characters where: +- `limit` - the minimum number of string characters required. +- `encoding` - is specified, the string length is calculated in bytes using the provided encoding. + +```javascript +var schema = Joi.string().min(2); +``` + +It can also be a reference to another field. + +```javascript +var schema = Joi.object({ + min: Joi.string().required(), + value: Joi.string().min(Joi.ref('min'), 'utf8').required() +}); +``` + +#### `string.max(limit, [encoding])` + +Specifies the maximum number of string characters where: +- `limit` - the maximum number of string characters allowed. +- `encoding` - is specified, the string length is calculated in bytes using the provided encoding. + +```javascript +var schema = Joi.string().max(10); +``` + +It can also be a reference to another field. + +```javascript +var schema = Joi.object({ + max: Joi.string().required(), + value: Joi.string().max(Joi.ref('max'), 'utf8').required() +}); +``` + +#### `string.creditCard()` + +Requires the number to be a credit card number (Using [Lunh +Algorithm](http://en.wikipedia.org/wiki/Luhn_algorithm)). + +```javascript +var schema = Joi.string().creditCard(); +``` + +#### `string.length(limit, [encoding])` + +Specifies the exact string length required where: +- `limit` - the required string length. +- `encoding` - is specified, the string length is calculated in bytes using the provided encoding. + +```javascript +var schema = Joi.string().length(5); +``` + +It can also be a reference to another field. + +```javascript +var schema = Joi.object({ + length: Joi.string().required(), + value: Joi.string().length(Joi.ref('length'), 'utf8').required() +}); +``` + +#### `string.regex(pattern, [name])` + +Defines a regular expression rule where: +- `pattern` - a regular expression object the string value must match against. +- `name` - optional name for patterns (useful with multiple patterns). Defaults to 'required'. + +```javascript +var schema = Joi.string().regex(/^[abc]+$/); +``` + +#### `string.replace(pattern, replacement)` + +Replace characters matching the given _pattern_ with the specified +_replacement_ string where: +- `pattern` - a regular expression object to match against, or a string of which _all_ occurrences will be replaced. +- `replacement` - the string that will replace the pattern. + + +```javascript +var schema = Joi.string().replace(/b/gi, 'x'); +schema.validate('abBc', function (err, value) { + // here value will be 'axxc' +}); +``` + +When `pattern` is a _string_ all its occurrences will be replaced. + +#### `string.alphanum()` + +Requires the string value to only contain a-z, A-Z, and 0-9. + +```javascript +var schema = Joi.string().alphanum(); +``` + +#### `string.token()` + +Requires the string value to only contain a-z, A-Z, 0-9, and underscore _. + +```javascript +var schema = Joi.string().token(); +``` + +#### `string.email([options])` + +Requires the string value to be a valid email address. + +- `options` - optional settings: + - `errorLevel` - Numerical threshold at which an email address is considered invalid. + - `tldWhitelist` - Specifies a list of acceptable TLDs. + - `minDomainAtoms` - Number of atoms required for the domain. Be careful since some domains, such as `io`, directly allow email. + +```javascript +var schema = Joi.string().email(); +``` + +#### `string.ip([options])` + +Requires the string value to be a valid ip address. + +- `options` - optional settings: + - `version` - One or more IP address versions to validate against. Valid values: `ipv4`, `ipv6`, `ipvfuture` + - `cidr` - Used to determine if a CIDR is allowed or not. Valid values: `optional`, `required`, `forbidden` + +```javascript +// Accept only ipv4 and ipv6 addresses with a CIDR +var schema = Joi.string().ip({ + version: [ + 'ipv4', + 'ipv6' + ], + cidr: 'required' +}); +``` + +#### `string.uri([options])` + +Requires the string value to be a valid [RFC 3986](http://tools.ietf.org/html/rfc3986) URI. + +- `options` - optional settings: + - `scheme` - Specifies one or more acceptable Schemes, should only include the scheme name. Can be an Array or String (strings are automatically escaped for use in a Regular Expression). + +```javascript +// Accept git or git http/https +var schema = Joi.string().uri({ + scheme: [ + 'git', + /git\+https?/ + ] +}); +``` + +#### `string.guid()` + +Requires the string value to be a valid GUID. + +```javascript +var schema = Joi.string().guid(); +``` + +#### `string.hex()` + +Requires the string value to be a valid hexadecimal string. + +```javascript +var schema = Joi.string().hex(); +``` + +#### `string.hostname()` + +Requires the string value to be a valid hostname as per [RFC1123](http://tools.ietf.org/html/rfc1123). + +```javascript +var schema = Joi.string().hostname(); +``` + +#### `string.lowercase()` + +Requires the string value to be all lowercase. If the validation `convert` option is on (enabled by default), the string +will be forced to lowercase. + +```javascript +var schema = Joi.string().lowercase(); +``` + +#### `string.uppercase()` + +Requires the string value to be all uppercase. If the validation `convert` option is on (enabled by default), the string +will be forced to uppercase. + +```javascript +var schema = Joi.string().uppercase(); +``` + +#### `string.trim()` + +Requires the string value to contain no whitespace before or after. If the validation `convert` option is on (enabled by +default), the string will be trimmed. + +```javascript +var schema = Joi.string().trim(); +``` + +#### `string.isoDate()` + +Requires the string value to be in valid ISO 8601 date format. + +```js +var schema = Joi.string().isoDate(); +``` + +### `alternatives` + +Generates a type that will match one of the provided alternative schemas via the [`try()`](#alternativestryschemas) +method. If no schemas are added, the type will not match any value except for `undefined`. + +Supports the same methods of the [`any()`](#any) type. + +Alternatives can be expressed using the shorter `[]` notation. + +```javascript +var alt = Joi.alternatives().try(Joi.number(), Joi.string()); +// Same as [Joi.number(), Joi.string()] +``` + +#### `alternatives.try(schemas)` + +Adds an alternative schema type for attempting to match against the validated value where: +- `schema` - an array of alternative **joi** types. Also supports providing each type as a separate argument. + +```javascript +var alt = Joi.alternatives().try(Joi.number(), Joi.string()); +alt.validate('a', function (err, value) { }); +``` + +#### `alternatives.when(ref, options)` + +Adds a conditional alternative schema type based on another key (not the same as `any.when()`) value where: +- `ref` - the key name or [reference](#refkey-options). +- `options` - an object with: + - `is` - the required condition **joi** type. + - `then` - the alternative schema type to **try** if the condition is true. Required if `otherwise` is missing. + - `otherwise` - the alternative schema type to **try** if the condition is false. Required if `then` is missing. + +```javascript +var schema = { + a: Joi.alternatives().when('b', { is: 5, then: Joi.string(), otherwise: Joi.number() }), + b: Joi.any() +}; +``` + +Note that `when()` only adds additional alternatives to try and does not impact the overall type. Setting +a `required()` rule on a single alternative will not apply to the overall key. For example, +this definition of `a`: + +```javascript +var schema = { + a: Joi.alternatives().when('b', { is: true, then: Joi.required() }), + b: Joi.boolean() +}; +``` + +Does not turn `a` into a required key when `b` is `true`. Instead, it tells the validator to try and match the +value to anything that's not `undefined`. However, since `Joi.alternatives()` by itself allows `undefined`, the rule +does not accomplish turning `a` to a required value. This rule is the same as `Joi.alternatives([Joi.required()])` +when `b` is `true` which will allow any value including `undefined`. + +To accomplish the desired result above use: + +```javascript +var schema = { + a: Joi.when('b', { is: true, then: Joi.required() }), + b: Joi.boolean() +}; +``` + +### `ref(key, [options])` + +Generates a reference to the value of the named key. References are resolved at validation time and in order of dependency +so that if one key validation depends on another, the dependent key is validated second after the reference is validated. +References support the following arguments: +- `key` - the reference target. References cannot point up the object tree, only to sibling keys, but they can point to + their siblings' children (e.g. 'a.b.c') using the `.` separator. If a `key` starts with `$` is signifies a context reference + which is looked up in the `context` option object. +- `options` - optional settings: + - `separator` - overrides the default `.` hierarchy separator. + - `contextPrefix` - overrides the default `$` context prefix signifier. + +Note that references can only be used where explicitly supported such as in `valid()` or `invalid()` rules. If upwards +(parents) references are needed, use [`object.assert()`](#objectassertref-schema-message). + +```javascript +var schema = Joi.object().keys({ + a: Joi.ref('b.c'), + b: { + c: Joi.any() + }, + c: Joi.ref('$x') +}); + +Joi.validate({ a: 5, b: { c: 5 } }, schema, { context: { x: 5 } }, function (err, value) {}); +``` + +## Errors + +Joi throws classical javascript `Error`s containing : +- `name` - `ValidationError`. +- `details` - an array of errors : + - `message` - string with a description of the error. + - `path` - dotted path to the key where the error happened. + - `type` - type of the error. + - `context` - object providing context of the error. +- `annotate` - function that returns a string with an annotated version of the object pointing at the places where errors occured. +- `_object` - the original object to validate.
@@ -0,0 +1,14 @@
+# How to contribute +We welcome contributions from the community and are pleased to have them. Please follow this guide when logging issues or making code changes. + +## Logging Issues +All issues should be created using the [new issue form](https://github.com/hapijs/joi/issues/new). Clearly describe the issue including steps to reproduce if there are any. Also, make sure to indicate the earliest version that has the issue being reported. + +## Patching Code +Code changes are welcome and should follow the guidelines below. + +* Fork the repository on GitHub. +* Fix the issue ensuring that your code follows the [style guide](https://github.com/hapijs/contrib/blob/master/Style.md). +* Add tests for your new code ensuring that you have 100% code coverage (we can help you reach 100% but will not merge without it). + * Run `npm test` to generate a report of test coverage +* [Pull requests](http://help.github.com/send-pull-requests/) should be made to the [master branch](https://github.com/hapijs/joi/tree/master).
@@ -0,0 +1,28 @@
+Copyright (c) 2012-2014, Walmart and other contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The names of any contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * * * + +The complete list of contributors can be found at: https://github.com/hapijs/joi/graphs/contributors
@@ -0,0 +1,90 @@
+ + +Object schema description language and validator for JavaScript objects. + +[](http://badge.fury.io/js/joi) +[](http://travis-ci.org/hapijs/joi) +[](https://david-dm.org/hapijs/joi) +[](https://david-dm.org/hapijs/joi#info=devDependencies) + +[](https://gitter.im/hapijs/joi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +Lead Maintainer: [Nicolas Morel](https://github.com/marsup) + +# Example + +```javascript +var Joi = require('joi'); + +var schema = Joi.object().keys({ + username: Joi.string().alphanum().min(3).max(30).required(), + password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/), + access_token: [Joi.string(), Joi.number()], + birthyear: Joi.number().integer().min(1900).max(2013), + email: Joi.string().email() +}).with('username', 'birthyear').without('password', 'access_token'); + +Joi.validate({ username: 'abc', birthyear: 1994 }, schema, function (err, value) { }); // err === null -> valid +``` + +The above schema defines the following constraints: +* `username` + * a required string + * must contain only alphanumeric characters + * at least 3 characters long but no more than 30 + * must be accompanied by `birthyear` +* `password` + * an optional string + * must satisfy the custom regex + * cannot appear together with `access_token` +* `access_token` + * an optional, unconstrained string or number +* `birthyear` + * an integer between 1900 and 2013 +* `email` + * a valid email address string + +# Usage + +Usage is a two steps process. First, a schema is constructed using the provided types and constraints: + +```javascript +var schema = { + a: Joi.string() +}; +``` + +Note that **joi** schema objects are immutable which means every additional rule added (e.g. `.min(5)`) will return a +new schema object. + +Then the value is validated against the schema: + +```javascript +Joi.validate({ a: 'a string' }, schema, function (err, value) { }); +``` + +If the value is valid, `null` is returned, otherwise an `Error` object. + +The schema can be a plain JavaScript object where every key is assigned a **joi** type, or it can be a **joi** type directly: + +```javascript +var schema = Joi.string().min(10); +``` + +If the schema is a **joi** type, the `schema.validate(value, callback)` can be called directly on the type. When passing a non-type schema object, +the module converts it internally to an object() type equivalent to: + +```javascript +var schema = Joi.object().keys({ + a: Joi.string() +}); +``` + +When validating a schema: + +* Keys are optional by default. +* Strings are utf-8 encoded by default. +* Rules are defined in an additive fashion and evaluated in order after whitelist and blacklist checks. + +# API +See the [API Reference](API.md).
@@ -0,0 +1,43 @@
+// This is an example of a survey to obtain the reputation of Parisians +// It contains examples of how to conditionally require keys based on values of other keys + +var Joi = require('../'); + +// This is a valid value for integer rating 1 - 5 +var intRating = Joi.number().integer().min(1).max(5); + +var schema = Joi.object().keys({ + // Do you know any French people? yes or no (required) + q1: Joi.boolean().required(), + // Do you know any Parisians? yes or no (required if answered yes in q1) + q2: Joi.boolean() + .when('q1', { is: true, then: Joi.required() }), + // How many french in paris do you know? 1-6, 6-10, 11-50 or 50+ (required if answered yes in q2) + q3: Joi.string() + .when('q2', { is: true, then: Joi.valid('1-5', '6-10', '11-50', '50+').required() }), + // Rate 20% of most friendly Parisians, from how many people you know answered in q3, individually on 1-5 rating + q4: Joi.array() + .when('q3', {is: '1-5', then: Joi.array().min(0).max(1).items(intRating).required() }) + .when('q3', {is: '6-10', then: Joi.array().min(1).max(2).items(intRating).required() }) + .when('q3', {is: '11-50', then: Joi.array().min(2).max(10).items(intRating).required() }) + .when('q3', {is: '50+', then: Joi.array().min(10).items(intRating).required() }), + // Rate remaining 80% of Parisians, from how many people you know answered in q3, individually on 1-5 rating + q5: Joi.array() + .when('q3', {is: '1-5', then: Joi.array().min(1).max(4).items(intRating).required() }) + .when('q3', {is: '6-10', then: Joi.array().min(4).max(8).items(intRating).required() }) + .when('q3', {is: '11-50', then: Joi.array().min(8).max(40).items(intRating).required() }) + .when('q3', {is: '50+', then: Joi.array().min(40).items(intRating).required().required() }), + // Rate the reputation of Parisians in general, 1-5 rating + q6: intRating.required() +}); + +var response = { + q1: true, + q2: true, + q3: '1-5', + q4: [5], + q5: [1], + q6: 2 +}; + +Joi.assert(response, schema);
@@ -0,0 +1,22 @@
+var Joi = require('../'); + + +var schema = Joi.object().options({ abortEarly: false }).keys({ + email: Joi.string().email().required().label('User Email'), + password: Joi.string().min(8).required(), + password_confirmation: Joi.any().valid(Joi.ref('password')).required().options({ language: { any: { allowOnly: 'must match password' }, label: 'Password Confirmation' } }).label('This label is not used because language.label takes precedence'), + first_name: Joi.string().required(), + last_name: Joi.string().required(), + company: Joi.string().optional() +}); + + +var data = { + email: 'not_a_valid_email_to_show_custom_label', + password: 'abcd1234', + password_confirmation: 'abc1', + first_name: 'Joe', + last_name: 'Doe' +}; + +Joi.assert(data, schema);
@@ -0,0 +1,17 @@
+var Joi = require('../'); + + +var schema = { + type: Joi.string().required(), + subtype: Joi.alternatives() + .when('type', {is: 'video', then: Joi.valid('mp4', 'wav')}) + .when('type', {is: 'audio', then: Joi.valid('mp3')}) + .when('type', {is: 'image', then: Joi.valid('jpg', 'png')}) + .when('type', {is: 'pdf' , then: Joi.valid('document')}) +}; + + +Joi.assert({ type: 'video', subtype: 'mp4' }, schema); // Pass +Joi.assert({ type: 'video', subtype: 'wav' }, schema); // Pass +Joi.assert({ type: 'other', subtype: 'something' }, schema); // Fail +Joi.assert({ type: 'audio', subtype: 'mp4' }, schema); // Fail
@@ -0,0 +1,21 @@
+var Toc = require('markdown-toc'); +var Fs = require('fs'); +var Package = require('./package.json'); + +var filename = './API.md'; + +var api = Fs.readFileSync(filename, 'utf8'); +var tocOptions = { + bullets: '-', + slugify: function (text) { + + return text.toLowerCase() + .replace(/\s/g, '-') + .replace(/[^\w-]/g, ''); + } +}; + +var output = Toc.insert(api, tocOptions) + .replace(/<!-- version -->(.|\n)*<!-- versionstop -->/, '<!-- version -->\n# ' + Package.version + ' API Reference\n<!-- versionstop -->'); + +Fs.writeFileSync(filename, output);
@@ -0,0 +1,152 @@
+// Load modules + +var Hoek = require('hoek'); +var Any = require('./any'); +var Cast = require('./cast'); +var Ref = require('./ref'); +var Errors = require('./errors'); + + +// Declare internals + +var internals = {}; + + +internals.Alternatives = function () { + + Any.call(this); + this._type = 'alternatives'; + this._invalids.remove(null); + + this._inner.matches = []; +}; + +Hoek.inherits(internals.Alternatives, Any); + + +internals.Alternatives.prototype._base = function (value, state, options) { + + var errors = []; + for (var i = 0, il = this._inner.matches.length; i < il; ++i) { + var item = this._inner.matches[i]; + var schema = item.schema; + if (!schema) { + var failed = item.is._validate(item.ref(state.parent, options), null, options, state.parent).errors; + schema = failed ? item.otherwise : item.then; + if (!schema) { + continue; + } + } + + var result = schema._validate(value, state, options); + if (!result.errors) { // Found a valid match + return result; + } + + errors = errors.concat(result.errors); + } + + return { errors: errors.length ? errors : Errors.create('alternatives.base', null, state, options) }; +}; + + +internals.Alternatives.prototype.try = function (/* schemas */) { + + + var schemas = Hoek.flatten(Array.prototype.slice.call(arguments)); + Hoek.assert(schemas.length, 'Cannot add other alternatives without at least one schema'); + + var obj = this.clone(); + + for (var i = 0, il = schemas.length; i < il; ++i) { + var cast = Cast.schema(schemas[i]); + if (cast._refs.length) { + obj._refs = obj._refs.concat(cast._refs); + } + obj._inner.matches.push({ schema: cast }); + } + + return obj; +}; + + +internals.Alternatives.prototype.when = function (ref, options) { + + Hoek.assert(Ref.isRef(ref) || typeof ref === 'string', 'Invalid reference:', ref); + Hoek.assert(options, 'Missing options'); + Hoek.assert(typeof options === 'object', 'Invalid options'); + Hoek.assert(options.hasOwnProperty('is'), 'Missing "is" directive'); + Hoek.assert(options.then !== undefined || options.otherwise !== undefined, 'options must have at least one of "then" or "otherwise"'); + + var obj = this.clone(); + var is = Cast.schema(options.is); + + if (options.is === null || !options.is.isJoi) { + + // Only apply required if this wasn't already a schema, we'll suppose people know what they're doing + is = is.required(); + } + + var item = { + ref: Cast.ref(ref), + is: is, + then: options.then !== undefined ? Cast.schema(options.then) : undefined, + otherwise: options.otherwise !== undefined ? Cast.schema(options.otherwise) : undefined + }; + + Ref.push(obj._refs, item.ref); + obj._refs = obj._refs.concat(item.is._refs); + + if (item.then && item.then._refs) { + obj._refs = obj._refs.concat(item.then._refs); + } + + if (item.otherwise && item.otherwise._refs) { + obj._refs = obj._refs.concat(item.otherwise._refs); + } + + obj._inner.matches.push(item); + + return obj; +}; + + +internals.Alternatives.prototype.describe = function () { + + var description = Any.prototype.describe.call(this); + var alternatives = []; + for (var i = 0, il = this._inner.matches.length; i < il; ++i) { + var item = this._inner.matches[i]; + if (item.schema) { + + // try() + + alternatives.push(item.schema.describe()); + } + else { + + // when() + + var when = { + ref: item.ref.toString(), + is: item.is.describe() + }; + + if (item.then) { + when.then = item.then.describe(); + } + + if (item.otherwise) { + when.otherwise = item.otherwise.describe(); + } + + alternatives.push(when); + } + } + + description.alternatives = alternatives; + return description; +}; + + +module.exports = new internals.Alternatives();
@@ -0,0 +1,899 @@
+// Load modules + +var Hoek = require('hoek'); +var Ref = require('./ref'); +var Errors = require('./errors'); +var Alternatives = null; // Delay-loaded to prevent circular dependencies +var Cast = null; + + +// Declare internals + +var internals = {}; + + +internals.defaults = { + abortEarly: true, + convert: true, + allowUnknown: false, + skipFunctions: false, + stripUnknown: false, + language: {}, + presence: 'optional', + raw: false, + strip: false, + noDefaults: false + + // context: null +}; + + +internals.checkOptions = function (options) { + + var optionType = { + abortEarly: 'boolean', + convert: 'boolean', + allowUnknown: 'boolean', + skipFunctions: 'boolean', + stripUnknown: 'boolean', + language: 'object', + presence: ['string', 'required', 'optional', 'forbidden', 'ignore'], + raw: 'boolean', + context: 'object', + strip: 'boolean', + noDefaults: 'boolean' + }; + + var keys = Object.keys(options); + for (var k = 0, kl = keys.length; k < kl; ++k) { + var key = keys[k]; + var opt = optionType[key]; + var type = opt; + var values = null; + + if (Array.isArray(opt)) { + type = opt[0]; + values = opt.slice(1); + } + + Hoek.assert(type, 'unknown key ' + key); + Hoek.assert(typeof options[key] === type, key + ' should be of type ' + type); + if (values) { + Hoek.assert(values.indexOf(options[key]) >= 0, key + ' should be one of ' + values.join(', ')); + } + } +}; + + +module.exports = internals.Any = function () { + + Cast = Cast || require('./cast'); + + this.isJoi = true; + this._type = 'any'; + this._settings = null; + this._valids = new internals.Set(); + this._invalids = new internals.Set(); + this._tests = []; + this._refs = []; + this._flags = { /* + presence: 'optional', // optional, required, forbidden, ignore + allowOnly: false, + allowUnknown: undefined, + default: undefined, + forbidden: false, + encoding: undefined, + insensitive: false, + trim: false, + case: undefined, // upper, lower + empty: undefined, + func: false + */ }; + + this._description = null; + this._unit = null; + this._notes = []; + this._tags = []; + this._examples = []; + this._meta = []; + + this._inner = {}; // Hash of arrays of immutable objects +}; + + +internals.Any.prototype.isImmutable = true; // Prevents Hoek from deep cloning schema objects + + +internals.Any.prototype.clone = function () { + + var obj = Object.create(Object.getPrototypeOf(this)); + + obj.isJoi = true; + obj._type = this._type; + obj._settings = internals.concatSettings(this._settings); + obj._valids = Hoek.clone(this._valids); + obj._invalids = Hoek.clone(this._invalids); + obj._tests = this._tests.slice(); + obj._refs = this._refs.slice(); + obj._flags = Hoek.clone(this._flags); + + obj._description = this._description; + obj._unit = this._unit; + obj._notes = this._notes.slice(); + obj._tags = this._tags.slice(); + obj._examples = this._examples.slice(); + obj._meta = this._meta.slice(); + + obj._inner = {}; + var inners = Object.keys(this._inner); + for (var i = 0, il = inners.length; i < il; ++i) { + var key = inners[i]; + obj._inner[key] = this._inner[key] ? this._inner[key].slice() : null; + } + + return obj; +}; + + +internals.Any.prototype.concat = function (schema) { + + Hoek.assert(schema && schema.isJoi, 'Invalid schema object'); + Hoek.assert(this._type === 'any' || schema._type === 'any' || schema._type === this._type, 'Cannot merge type', this._type, 'with another type:', schema._type); + + var obj = this.clone(); + + if (this._type === 'any' && schema._type !== 'any') { + + // Reset values as if we were "this" + var tmpObj = schema.clone(); + var keysToRestore = ['_settings', '_valids', '_invalids', '_tests', '_refs', '_flags', '_description', '_unit', + '_notes', '_tags', '_examples', '_meta', '_inner']; + + for (var j = 0, jl = keysToRestore.length; j < jl; ++j) { + tmpObj[keysToRestore[j]] = obj[keysToRestore[j]]; + } + + obj = tmpObj; + } + + obj._settings = obj._settings ? internals.concatSettings(obj._settings, schema._settings) : schema._settings; + obj._valids.merge(schema._valids, schema._invalids); + obj._invalids.merge(schema._invalids, schema._valids); + obj._tests = obj._tests.concat(schema._tests); + obj._refs = obj._refs.concat(schema._refs); + Hoek.merge(obj._flags, schema._flags); + + obj._description = schema._description || obj._description; + obj._unit = schema._unit || obj._unit; + obj._notes = obj._notes.concat(schema._notes); + obj._tags = obj._tags.concat(schema._tags); + obj._examples = obj._examples.concat(schema._examples); + obj._meta = obj._meta.concat(schema._meta); + + var inners = Object.keys(schema._inner); + var isObject = obj._type === 'object'; + for (var i = 0, il = inners.length; i < il; ++i) { + var key = inners[i]; + var source = schema._inner[key]; + if (source) { + var target = obj._inner[key]; + if (target) { + if (isObject && key === 'children') { + var keys = {}; + + for (var k = 0, kl = target.length; k < kl; ++k) { + keys[target[k].key] = k; + } + + for (k = 0, kl = source.length; k < kl; ++k) { + var sourceKey = source[k].key; + if (keys[sourceKey] >= 0) { + target[keys[sourceKey]] = { + key: sourceKey, + schema: target[keys[sourceKey]].schema.concat(source[k].schema) + }; + } + else { + target.push(source[k]); + } + } + } + else { + obj._inner[key] = obj._inner[key].concat(source); + } + } + else { + obj._inner[key] = source.slice(); + } + } + } + + return obj; +}; + + +internals.Any.prototype._test = function (name, arg, func) { + + Hoek.assert(!this._flags.allowOnly, 'Cannot define rules when valid values specified'); + + var obj = this.clone(); + obj._tests.push({ func: func, name: name, arg: arg }); + return obj; +}; + + +internals.Any.prototype.options = function (options) { + + Hoek.assert(!options.context, 'Cannot override context'); + internals.checkOptions(options); + + var obj = this.clone(); + obj._settings = internals.concatSettings(obj._settings, options); + return obj; +}; + + +internals.Any.prototype.strict = function (isStrict) { + + var obj = this.clone(); + obj._settings = obj._settings || {}; + obj._settings.convert = isStrict === undefined ? false : !isStrict; + return obj; +}; + + +internals.Any.prototype.raw = function (isRaw) { + + var obj = this.clone(); + obj._settings = obj._settings || {}; + obj._settings.raw = isRaw === undefined ? true : isRaw; + return obj; +}; + + +internals.Any.prototype._allow = function () { + + var values = Hoek.flatten(Array.prototype.slice.call(arguments)); + for (var i = 0, il = values.length; i < il; ++i) { + var value = values[i]; + + Hoek.assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined'); + this._invalids.remove(value); + this._valids.add(value, this._refs); + } +}; + + +internals.Any.prototype.allow = function () { + + var obj = this.clone(); + obj._allow.apply(obj, arguments); + return obj; +}; + + +internals.Any.prototype.valid = internals.Any.prototype.only = internals.Any.prototype.equal = function () { + + Hoek.assert(!this._tests.length, 'Cannot set valid values when rules specified'); + + var obj = this.allow.apply(this, arguments); + obj._flags.allowOnly = true; + return obj; +}; + + +internals.Any.prototype.invalid = internals.Any.prototype.disallow = internals.Any.prototype.not = function (value) { + + var obj = this.clone(); + var values = Hoek.flatten(Array.prototype.slice.call(arguments)); + for (var i = 0, il = values.length; i < il; ++i) { + value = values[i]; + + Hoek.assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined'); + obj._valids.remove(value); + obj._invalids.add(value, this._refs); + } + + return obj; +}; + + +internals.Any.prototype.required = internals.Any.prototype.exist = function () { + + var obj = this.clone(); + obj._flags.presence = 'required'; + return obj; +}; + + +internals.Any.prototype.optional = function () { + + var obj = this.clone(); + obj._flags.presence = 'optional'; + return obj; +}; + + +internals.Any.prototype.forbidden = function () { + + var obj = this.clone(); + obj._flags.presence = 'forbidden'; + return obj; +}; + + +internals.Any.prototype.strip = function () { + + var obj = this.clone(); + obj._flags.strip = true; + return obj; +}; + + +internals.Any.prototype.applyFunctionToChildren = function (children, fn, args, root) { + + children = [].concat(children); + + if (children.length !== 1 || children[0] !== '') { + root = root ? (root + '.') : ''; + + var extraChildren = (children[0] === '' ? children.slice(1) : children).map(function (child) { + + return root + child; + }); + + throw new Error('unknown key(s) ' + extraChildren.join(', ')); + } + + return this[fn].apply(this, args); +}; + + +internals.Any.prototype.default = function (value, description) { + + if (typeof value === 'function' && + !Ref.isRef(value)) { + + if (!value.description && + description) { + + value.description = description; + } + + if (!this._flags.func) { + Hoek.assert(typeof value.description === 'string' && value.description.length > 0, 'description must be provided when default value is a function'); + } + } + + var obj = this.clone(); + obj._flags.default = value; + Ref.push(obj._refs, value); + return obj; +}; + + +internals.Any.prototype.empty = function (schema) { + + var obj; + if (schema === undefined) { + obj = this.clone(); + obj._flags.empty = undefined; + } + else { + schema = Cast.schema(schema); + + obj = this.clone(); + obj._flags.empty = schema; + } + + return obj; +}; + + +internals.Any.prototype.when = function (ref, options) { + + Hoek.assert(options && typeof options === 'object', 'Invalid options'); + Hoek.assert(options.then !== undefined || options.otherwise !== undefined, 'options must have at least one of "then" or "otherwise"'); + + var then = options.then ? this.concat(Cast.schema(options.then)) : this; + var otherwise = options.otherwise ? this.concat(Cast.schema(options.otherwise)) : this; + + Alternatives = Alternatives || require('./alternatives'); + var obj = Alternatives.when(ref, { is: options.is, then: then, otherwise: otherwise }); + obj._flags.presence = 'ignore'; + return obj; +}; + + +internals.Any.prototype.description = function (desc) { + + Hoek.assert(desc && typeof desc === 'string', 'Description must be a non-empty string'); + + var obj = this.clone(); + obj._description = desc; + return obj; +}; + + +internals.Any.prototype.notes = function (notes) { + + Hoek.assert(notes && (typeof notes === 'string' || Array.isArray(notes)), 'Notes must be a non-empty string or array'); + + var obj = this.clone(); + obj._notes = obj._notes.concat(notes); + return obj; +}; + + +internals.Any.prototype.tags = function (tags) { + + Hoek.assert(tags && (typeof tags === 'string' || Array.isArray(tags)), 'Tags must be a non-empty string or array'); + + var obj = this.clone(); + obj._tags = obj._tags.concat(tags); + return obj; +}; + +internals.Any.prototype.meta = function (meta) { + + Hoek.assert(meta !== undefined, 'Meta cannot be undefined'); + + var obj = this.clone(); + obj._meta = obj._meta.concat(meta); + return obj; +}; + + +internals.Any.prototype.example = function (value) { + + Hoek.assert(arguments.length, 'Missing example'); + var result = this._validate(value, null, internals.defaults); + Hoek.assert(!result.errors, 'Bad example:', result.errors && Errors.process(result.errors, value)); + + var obj = this.clone(); + obj._examples = obj._examples.concat(value); + return obj; +}; + + +internals.Any.prototype.unit = function (name) { + + Hoek.assert(name && typeof name === 'string', 'Unit name must be a non-empty string'); + + var obj = this.clone(); + obj._unit = name; + return obj; +}; + + +internals._try = function (fn, arg) { + + var err; + var result; + + try { + result = fn.call(null, arg); + } catch (e) { + err = e; + } + + return { + value: result, + error: err + }; +}; + + +internals.Any.prototype._validate = function (value, state, options, reference) { + + var self = this; + var originalValue = value; + + // Setup state and settings + + state = state || { key: '', path: '', parent: null, reference: reference }; + + if (this._settings) { + options = internals.concatSettings(options, this._settings); + } + + var errors = []; + var finish = function () { + + var finalValue; + + if (!self._flags.strip) { + if (value !== undefined) { + finalValue = options.raw ? originalValue : value; + } + else if (options.noDefaults) { + finalValue = originalValue; + } + else if (Ref.isRef(self._flags.default)) { + finalValue = self._flags.default(state.parent, options); + } + else if (typeof self._flags.default === 'function' && + !(self._flags.func && !self._flags.default.description)) { + + var arg; + + if (state.parent !== null && + self._flags.default.length > 0) { + + arg = Hoek.clone(state.parent); + } + + var defaultValue = internals._try(self._flags.default, arg); + finalValue = defaultValue.value; + if (defaultValue.error) { + errors.push(Errors.create('any.default', defaultValue.error, state, options)); + } + } + else { + finalValue = Hoek.clone(self._flags.default); + } + } + + return { + value: finalValue, + errors: errors.length ? errors : null + }; + }; + + // Check presence requirements + + var presence = this._flags.presence || options.presence; + if (presence === 'optional') { + if (value === undefined) { + var isDeepDefault = this._flags.hasOwnProperty('default') && this._flags.default === undefined; + if (isDeepDefault && this._type === 'object') { + value = {}; + } + else { + return finish(); + } + } + } + else if (presence === 'required' && + value === undefined) { + + errors.push(Errors.create('any.required', null, state, options)); + return finish(); + } + else if (presence === 'forbidden') { + if (value === undefined) { + return finish(); + } + + errors.push(Errors.create('any.unknown', null, state, options)); + return finish(); + } + + if (this._flags.empty && !this._flags.empty._validate(value, null, internals.defaults).errors) { + value = undefined; + return finish(); + } + + // Check allowed and denied values using the original value + + if (this._valids.has(value, state, options, this._flags.insensitive)) { + return finish(); + } + + if (this._invalids.has(value, state, options, this._flags.insensitive)) { + errors.push(Errors.create(value === '' ? 'any.empty' : 'any.invalid', null, state, options)); + if (options.abortEarly || + value === undefined) { // No reason to keep validating missing value + + return finish(); + } + } + + // Convert value and validate type + + if (this._base) { + var base = this._base.call(this, value, state, options); + if (base.errors) { + value = base.value; + errors = errors.concat(base.errors); + return finish(); // Base error always aborts early + } + + if (base.value !== value) { + value = base.value; + + // Check allowed and denied values using the converted value + + if (this._valids.has(value, state, options, this._flags.insensitive)) { + return finish(); + } + + if (this._invalids.has(value, state, options, this._flags.insensitive)) { + errors.push(Errors.create('any.invalid', null, state, options)); + if (options.abortEarly) { + return finish(); + } + } + } + } + + // Required values did not match + + if (this._flags.allowOnly) { + errors.push(Errors.create('any.allowOnly', { valids: this._valids.values({ stripUndefined: true }) }, state, options)); + if (options.abortEarly) { + return finish(); + } + } + + // Helper.validate tests + + for (var i = 0, il = this._tests.length; i < il; ++i) { + var test = this._tests[i]; + var err = test.func.call(this, value, state, options); + if (err) { + errors.push(err); + if (options.abortEarly) { + return finish(); + } + } + } + + return finish(); +}; + + +internals.Any.prototype._validateWithOptions = function (value, options, callback) { + + if (options) { + internals.checkOptions(options); + } + + var settings = internals.concatSettings(internals.defaults, options); + var result = this._validate(value, null, settings); + var errors = Errors.process(result.errors, value); + + if (callback) { + return callback(errors, result.value); + } + + return { error: errors, value: result.value }; +}; + + +internals.Any.prototype.validate = function (value, callback) { + + var result = this._validate(value, null, internals.defaults); + var errors = Errors.process(result.errors, value); + + if (callback) { + return callback(errors, result.value); + } + + return { error: errors, value: result.value }; +}; + + +internals.Any.prototype.describe = function () { + + var description = { + type: this._type + }; + + var flags = Object.keys(this._flags); + if (flags.length) { + if (this._flags.empty) { + description.flags = {}; + for (var f = 0, fl = flags.length; f < fl; ++f) { + var flag = flags[f]; + description.flags[flag] = flag === 'empty' ? this._flags[flag].describe() : this._flags[flag]; + } + } + else { + description.flags = this._flags; + } + } + + if (this._description) { + description.description = this._description; + } + + if (this._notes.length) { + description.notes = this._notes; + } + + if (this._tags.length) { + description.tags = this._tags; + } + + if (this._meta.length) { + description.meta = this._meta; + } + + if (this._examples.length) { + description.examples = this._examples; + } + + if (this._unit) { + description.unit = this._unit; + } + + var valids = this._valids.values(); + if (valids.length) { + description.valids = valids; + } + + var invalids = this._invalids.values(); + if (invalids.length) { + description.invalids = invalids; + } + + description.rules = []; + + for (var i = 0, il = this._tests.length; i < il; ++i) { + var validator = this._tests[i]; + var item = { name: validator.name }; + if (validator.arg !== void 0) { + item.arg = validator.arg; + } + description.rules.push(item); + } + + if (!description.rules.length) { + delete description.rules; + } + + var label = Hoek.reach(this._settings, 'language.label'); + if (label) { + description.label = label; + } + + return description; +}; + +internals.Any.prototype.label = function (name) { + + Hoek.assert(name && typeof name === 'string', 'Label name must be a non-empty string'); + + var obj = this.clone(); + var options = { language: { label: name } }; + + // If language.label is set, it should override this label + obj._settings = internals.concatSettings(options, obj._settings); + return obj; +}; + + +// Set + +internals.Set = function () { + + this._set = []; +}; + + +internals.Set.prototype.add = function (value, refs) { + + Hoek.assert(value === null || value === undefined || value instanceof Date || Buffer.isBuffer(value) || Ref.isRef(value) || (typeof value !== 'function' && typeof value !== 'object'), 'Value cannot be an object or function'); + + if (typeof value !== 'function' && + this.has(value, null, null, false)) { + + return; + } + + Ref.push(refs, value); + this._set.push(value); +}; + + +internals.Set.prototype.merge = function (add, remove) { + + for (var i = 0, il = add._set.length; i < il; ++i) { + this.add(add._set[i]); + } + + for (i = 0, il = remove._set.length; i < il; ++i) { + this.remove(remove._set[i]); + } +}; + + +internals.Set.prototype.remove = function (value) { + + this._set = this._set.filter(function (item) { + + return value !== item; + }); +}; + + +internals.Set.prototype.has = function (value, state, options, insensitive) { + + for (var i = 0, il = this._set.length; i < il; ++i) { + var items = this._set[i]; + + if (Ref.isRef(items)) { + items = items(state.reference || state.parent, options); + } + + if (!Array.isArray(items)) { + items = [items]; + } + + for (var j = 0, jl = items.length; j < jl; ++j) { + var item = items[j]; + if (typeof value !== typeof item) { + continue; + } + + if (value === item || + (value instanceof Date && item instanceof Date && value.getTime() === item.getTime()) || + (insensitive && typeof value === 'string' && value.toLowerCase() === item.toLowerCase()) || + (Buffer.isBuffer(value) && Buffer.isBuffer(item) && value.length === item.length && value.toString('binary') === item.toString('binary'))) { + + return true; + } + } + } + + return false; +}; + + +internals.Set.prototype.values = function (options) { + + if (options && options.stripUndefined) { + var values = []; + + for (var i = 0, il = this._set.length; i < il; ++i) { + var item = this._set[i]; + if (item !== undefined) { + values.push(item); + } + } + + return values; + } + + return this._set.slice(); +}; + + +internals.concatSettings = function (target, source) { + + // Used to avoid cloning context + + if (!target && + !source) { + + return null; + } + + var key, obj = {}; + + if (target) { + var tKeys = Object.keys(target); + for (var i = 0, il = tKeys.length; i < il; ++i) { + key = tKeys[i]; + obj[key] = target[key]; + } + } + + if (source) { + var sKeys = Object.keys(source); + for (var j = 0, jl = sKeys.length; j < jl; ++j) { + key = sKeys[j]; + if (key !== 'language' || + !obj.hasOwnProperty(key)) { + + obj[key] = source[key]; + } + else { + obj[key] = Hoek.applyToDefaults(obj[key], source[key]); + } + } + } + + return obj; +};
@@ -0,0 +1,517 @@
+// Load modules + +var Any = require('./any'); +var Cast = require('./cast'); +var Errors = require('./errors'); +var Hoek = require('hoek'); + + +// Declare internals + +var internals = {}; + + +internals.fastSplice = function (arr, i) { + + var il = arr.length; + var pos = i; + + while (pos < il) { + arr[pos++] = arr[pos]; + } + + --arr.length; +}; + + +internals.Array = function () { + + Any.call(this); + this._type = 'array'; + this._inner.items = []; + this._inner.ordereds = []; + this._inner.inclusions = []; + this._inner.exclusions = []; + this._inner.requireds = []; + this._flags.sparse = false; +}; + +Hoek.inherits(internals.Array, Any); + + +internals.Array.prototype._base = function (value, state, options) { + + var result = { + value: value + }; + + if (typeof value === 'string' && + options.convert) { + + try { + var converted = JSON.parse(value); + if (Array.isArray(converted)) { + result.value = converted; + } + } + catch (e) { } + } + + var isArray = Array.isArray(result.value); + var wasArray = isArray; + if (options.convert && this._flags.single && !isArray) { + result.value = [result.value]; + isArray = true; + } + + if (!isArray) { + result.errors = Errors.create('array.base', null, state, options); + return result; + } + + if (this._inner.inclusions.length || + this._inner.exclusions.length || + !this._flags.sparse) { + + // Clone the array so that we don't modify the original + if (wasArray) { + result.value = result.value.slice(0); + } + + result.errors = internals.checkItems.call(this, result.value, wasArray, state, options); + + if (result.errors && wasArray && options.convert && this._flags.single) { + + // Attempt a 2nd pass by putting the array inside one. + var previousErrors = result.errors; + + result.value = [result.value]; + result.errors = internals.checkItems.call(this, result.value, wasArray, state, options); + + if (result.errors) { + + // Restore previous errors and value since this didn't validate either. + result.errors = previousErrors; + result.value = result.value[0]; + } + } + } + + return result; +}; + + +internals.checkItems = function (items, wasArray, state, options) { + + var errors = []; + var errored; + + var requireds = this._inner.requireds.slice(); + var ordereds = this._inner.ordereds.slice(); + var inclusions = this._inner.inclusions.concat(requireds); + + for (var v = 0, vl = items.length; v < vl; ++v) { + errored = false; + var item = items[v]; + var isValid = false; + var localState = { key: v, path: (state.path ? state.path + '.' : '') + v, parent: items, reference: state.reference }; + var res; + + // Sparse + + if (!this._flags.sparse && item === undefined) { + errors.push(Errors.create('array.sparse', null, { key: state.key, path: localState.path }, options)); + + if (options.abortEarly) { + return errors; + } + + continue; + } + + // Exclusions + + for (var i = 0, il = this._inner.exclusions.length; i < il; ++i) { + res = this._inner.exclusions[i]._validate(item, localState, {}); // Not passing options to use defaults + + if (!res.errors) { + errors.push(Errors.create(wasArray ? 'array.excludes' : 'array.excludesSingle', { pos: v, value: item }, { key: state.key, path: localState.path }, options)); + errored = true; + + if (options.abortEarly) { + return errors; + } + + break; + } + } + + if (errored) { + continue; + } + + // Ordered + if (this._inner.ordereds.length) { + if (ordereds.length > 0) { + var ordered = ordereds.shift(); + res = ordered._validate(item, localState, options); + if (!res.errors) { + if (ordered._flags.strip) { + internals.fastSplice(items, v); + --v; + --vl; + } + else { + items[v] = res.value; + } + } + else { + errors.push(Errors.create('array.ordered', { pos: v, reason: res.errors, value: item }, { key: state.key, path: localState.path }, options)); + if (options.abortEarly) { + return errors; + } + } + continue; + } + else if (!this._inner.items.length) { + errors.push(Errors.create('array.orderedLength', { pos: v, limit: this._inner.ordereds.length }, { key: state.key, path: localState.path }, options)); + if (options.abortEarly) { + return errors; + } + continue; + } + } + + // Requireds + + var requiredChecks = []; + for (i = 0, il = requireds.length; i < il; ++i) { + res = requiredChecks[i] = requireds[i]._validate(item, localState, options); + if (!res.errors) { + items[v] = res.value; + isValid = true; + internals.fastSplice(requireds, i); + --i; + --il; + break; + } + } + + if (isValid) { + continue; + } + + // Inclusions + + for (i = 0, il = inclusions.length; i < il; ++i) { + var inclusion = inclusions[i]; + + // Avoid re-running requireds that already didn't match in the previous loop + var previousCheck = requireds.indexOf(inclusion); + if (previousCheck !== -1) { + res = requiredChecks[previousCheck]; + } + else { + res = inclusion._validate(item, localState, options); + + if (!res.errors) { + if (inclusion._flags.strip) { + internals.fastSplice(items, v); + --v; + --vl; + } + else { + items[v] = res.value; + } + isValid = true; + break; + } + } + + // Return the actual error if only one inclusion defined + if (il === 1) { + if (options.stripUnknown) { + internals.fastSplice(items, v); + --v; + --vl; + isValid = true; + break; + } + + errors.push(Errors.create(wasArray ? 'array.includesOne' : 'array.includesOneSingle', { pos: v, reason: res.errors, value: item }, { key: state.key, path: localState.path }, options)); + errored = true; + + if (options.abortEarly) { + return errors; + } + + break; + } + } + + if (errored) { + continue; + } + + if (this._inner.inclusions.length && !isValid) { + if (options.stripUnknown) { + internals.fastSplice(items, v); + --v; + --vl; + continue; + } + + errors.push(Errors.create(wasArray ? 'array.includes' : 'array.includesSingle', { pos: v, value: item }, { key: state.key, path: localState.path }, options)); + + if (options.abortEarly) { + return errors; + } + } + } + + if (requireds.length) { + internals.fillMissedErrors(errors, requireds, state, options); + } + + if (ordereds.length) { + internals.fillOrderedErrors(errors, ordereds, state, options); + } + + return errors.length ? errors : null; +}; + +internals.fillMissedErrors = function (errors, requireds, state, options) { + + var knownMisses = []; + var unknownMisses = 0; + for (var i = 0, il = requireds.length; i < il; ++i) { + var label = Hoek.reach(requireds[i], '_settings.language.label'); + if (label) { + knownMisses.push(label); + } + else { + ++unknownMisses; + } + } + + if (knownMisses.length) { + if (unknownMisses) { + errors.push(Errors.create('array.includesRequiredBoth', { knownMisses: knownMisses, unknownMisses: unknownMisses }, { key: state.key, path: state.patk }, options)); + } + else { + errors.push(Errors.create('array.includesRequiredKnowns', { knownMisses: knownMisses }, { key: state.key, path: state.path }, options)); + } + } + else { + errors.push(Errors.create('array.includesRequiredUnknowns', { unknownMisses: unknownMisses }, { key: state.key, path: state.path }, options)); + } +}; + +internals.fillOrderedErrors = function (errors, ordereds, state, options) { + + var requiredOrdereds = []; + + for (var i = 0, il = ordereds.length; i < il; ++i) { + var presence = Hoek.reach(ordereds[i], '_flags.presence'); + if (presence === 'required') { + requiredOrdereds.push(ordereds[i]); + } + } + + if (requiredOrdereds.length) { + internals.fillMissedErrors(errors, requiredOrdereds, state, options); + } +}; + +internals.Array.prototype.describe = function () { + + var description = Any.prototype.describe.call(this); + + if (this._inner.ordereds.length) { + description.orderedItems = []; + + for (var o = 0, ol = this._inner.ordereds.length; o < ol; ++o) { + description.orderedItems.push(this._inner.ordereds[o].describe()); + } + } + + if (this._inner.items.length) { + description.items = []; + + for (var i = 0, il = this._inner.items.length; i < il; ++i) { + description.items.push(this._inner.items[i].describe()); + } + } + + return description; +}; + + +internals.Array.prototype.items = function () { + + var obj = this.clone(); + + Hoek.flatten(Array.prototype.slice.call(arguments)).forEach(function (type, index) { + + try { + type = Cast.schema(type); + } + catch (castErr) { + if (castErr.hasOwnProperty('path')) { + castErr.path = index + '.' + castErr.path; + } + else { + castErr.path = index; + } + castErr.message += '(' + castErr.path + ')'; + throw castErr; + } + + obj._inner.items.push(type); + + if (type._flags.presence === 'required') { + obj._inner.requireds.push(type); + } + else if (type._flags.presence === 'forbidden') { + obj._inner.exclusions.push(type.optional()); + } + else { + obj._inner.inclusions.push(type); + } + }); + + return obj; +}; + + +internals.Array.prototype.ordered = function () { + + var obj = this.clone(); + + Hoek.flatten(Array.prototype.slice.call(arguments)).forEach(function (type, index) { + + try { + type = Cast.schema(type); + } + catch (castErr) { + if (castErr.hasOwnProperty('path')) { + castErr.path = index + '.' + castErr.path; + } + else { + castErr.path = index; + } + castErr.message += '(' + castErr.path + ')'; + throw castErr; + } + obj._inner.ordereds.push(type); + }); + + return obj; +}; + + +internals.Array.prototype.min = function (limit) { + + Hoek.assert(Hoek.isInteger(limit) && limit >= 0, 'limit must be a positive integer'); + + return this._test('min', limit, function (value, state, options) { + + if (value.length >= limit) { + return null; + } + + return Errors.create('array.min', { limit: limit, value: value }, state, options); + }); +}; + + +internals.Array.prototype.max = function (limit) { + + Hoek.assert(Hoek.isInteger(limit) && limit >= 0, 'limit must be a positive integer'); + + return this._test('max', limit, function (value, state, options) { + + if (value.length <= limit) { + return null; + } + + return Errors.create('array.max', { limit: limit, value: value }, state, options); + }); +}; + + +internals.Array.prototype.length = function (limit) { + + Hoek.assert(Hoek.isInteger(limit) && limit >= 0, 'limit must be a positive integer'); + + return this._test('length', limit, function (value, state, options) { + + if (value.length === limit) { + return null; + } + + return Errors.create('array.length', { limit: limit, value: value }, state, options); + }); +}; + + +internals.Array.prototype.unique = function () { + + return this._test('unique', undefined, function (value, state, options) { + + var found = { + string: {}, + number: {}, + undefined: {}, + boolean: {}, + object: [], + function: [] + }; + + for (var i = 0, il = value.length; i < il; ++i) { + var item = value[i]; + var type = typeof item; + var records = found[type]; + + // All available types are supported, so it's not possible to reach 100% coverage without ignoring this line. + // I still want to keep the test for future js versions with new types (eg. Symbol). + if (/* $lab:coverage:off$ */ records /* $lab:coverage:on$ */) { + if (Array.isArray(records)) { + for (var r = 0, rl = records.length; r < rl; ++r) { + if (Hoek.deepEqual(records[r], item)) { + return Errors.create('array.unique', { pos: i, value: item }, state, options); + } + } + + records.push(item); + } + else { + if (records[item]) { + return Errors.create('array.unique', { pos: i, value: item }, state, options); + } + + records[item] = true; + } + } + } + }); +}; + + +internals.Array.prototype.sparse = function (enabled) { + + var obj = this.clone(); + obj._flags.sparse = enabled === undefined ? true : !!enabled; + return obj; +}; + + +internals.Array.prototype.single = function (enabled) { + + var obj = this.clone(); + obj._flags.single = enabled === undefined ? true : !!enabled; + return obj; +}; + + +module.exports = new internals.Array();
@@ -0,0 +1,98 @@
+// Load modules + +var Any = require('./any'); +var Errors = require('./errors'); +var Hoek = require('hoek'); + + +// Declare internals + +var internals = {}; + + +internals.Binary = function () { + + Any.call(this); + this._type = 'binary'; +}; + +Hoek.inherits(internals.Binary, Any); + + +internals.Binary.prototype._base = function (value, state, options) { + + var result = { + value: value + }; + + if (typeof value === 'string' && + options.convert) { + + try { + var converted = new Buffer(value, this._flags.encoding); + result.value = converted; + } + catch (e) { } + } + + result.errors = Buffer.isBuffer(result.value) ? null : Errors.create('binary.base', null, state, options); + return result; +}; + + +internals.Binary.prototype.encoding = function (encoding) { + + Hoek.assert(Buffer.isEncoding(encoding), 'Invalid encoding:', encoding); + + var obj = this.clone(); + obj._flags.encoding = encoding; + return obj; +}; + + +internals.Binary.prototype.min = function (limit) { + + Hoek.assert(Hoek.isInteger(limit) && limit >= 0, 'limit must be a positive integer'); + + return this._test('min', limit, function (value, state, options) { + + if (value.length >= limit) { + return null; + } + + return Errors.create('binary.min', { limit: limit, value: value }, state, options); + }); +}; + + +internals.Binary.prototype.max = function (limit) { + + Hoek.assert(Hoek.isInteger(limit) && limit >= 0, 'limit must be a positive integer'); + + return this._test('max', limit, function (value, state, options) { + + if (value.length <= limit) { + return null; + } + + return Errors.create('binary.max', { limit: limit, value: value }, state, options); + }); +}; + + +internals.Binary.prototype.length = function (limit) { + + Hoek.assert(Hoek.isInteger(limit) && limit >= 0, 'limit must be a positive integer'); + + return this._test('length', limit, function (value, state, options) { + + if (value.length === limit) { + return null; + } + + return Errors.create('binary.length', { limit: limit, value: value }, state, options); + }); +}; + + +module.exports = new internals.Binary();
@@ -0,0 +1,41 @@
+// Load modules + +var Any = require('./any'); +var Errors = require('./errors'); +var Hoek = require('hoek'); + + +// Declare internals + +var internals = {}; + + +internals.Boolean = function () { + + Any.call(this); + this._type = 'boolean'; +}; + +Hoek.inherits(internals.Boolean, Any); + + +internals.Boolean.prototype._base = function (value, state, options) { + + var result = { + value: value + }; + + if (typeof value === 'string' && + options.convert) { + + var lower = value.toLowerCase(); + result.value = (lower === 'true' || lower === 'yes' || lower === 'on' ? true + : (lower === 'false' || lower === 'no' || lower === 'off' ? false : value)); + } + + result.errors = (typeof result.value === 'boolean') ? null : Errors.create('boolean.base', null, state, options); + return result; +}; + + +module.exports = new internals.Boolean();
@@ -0,0 +1,75 @@
+// Load modules + +var Hoek = require('hoek'); +var Ref = require('./ref'); + +// Type modules are delay-loaded to prevent circular dependencies + + +// Declare internals + +var internals = { + any: null, + date: require('./date'), + string: require('./string'), + number: require('./number'), + boolean: require('./boolean'), + alt: null, + object: null +}; + + +exports.schema = function (config) { + + internals.any = internals.any || new (require('./any'))(); + internals.alt = internals.alt || require('./alternatives'); + internals.object = internals.object || require('./object'); + + if (config && + typeof config === 'object') { + + if (config.isJoi) { + return config; + } + + if (Array.isArray(config)) { + return internals.alt.try(config); + } + + if (config instanceof RegExp) { + return internals.string.regex(config); + } + + if (config instanceof Date) { + return internals.date.valid(config); + } + + return internals.object.keys(config); + } + + if (typeof config === 'string') { + return internals.string.valid(config); + } + + if (typeof config === 'number') { + return internals.number.valid(config); + } + + if (typeof config === 'boolean') { + return internals.boolean.valid(config); + } + + if (Ref.isRef(config)) { + return internals.any.valid(config); + } + + Hoek.assert(config === null, 'Invalid schema content:', config); + + return internals.any.valid(null); +}; + + +exports.ref = function (id) { + + return Ref.isRef(id) ? id : Ref.create(id); +};
@@ -0,0 +1,168 @@
+// Load modules + +var Any = require('./any'); +var Errors = require('./errors'); +var Ref = require('./ref'); +var Hoek = require('hoek'); +var Moment = require('moment'); + + +// Declare internals + +var internals = {}; + +internals.isoDate = /^(?:\d{4}(?!\d{2}\b))(?:(-?)(?:(?:0[1-9]|1[0-2])(?:\1(?:[12]\d|0[1-9]|3[01]))?|W(?:[0-4]\d|5[0-2])(?:-?[1-7])?|(?:00[1-9]|0[1-9]\d|[12]\d{2}|3(?:[0-5]\d|6[1-6])))(?![T]$|[T][\d]+Z$)(?:[T\s](?:(?:(?:[01]\d|2[0-3])(?:(:?)[0-5]\d)?|24\:?00)(?:[.,]\d+(?!:))?)(?:\2[0-5]\d(?:[.,]\d+)?)?(?:[Z]|(?:[+-])(?:[01]\d|2[0-3])(?::?[0-5]\d)?)?)?)?$/; +internals.invalidDate = new Date(''); +internals.isIsoDate = (function () { + + var isoString = internals.isoDate.toString(); + + return function (date) { + + return date && (date.toString() === isoString); + }; +})(); + +internals.Date = function () { + + Any.call(this); + this._type = 'date'; +}; + +Hoek.inherits(internals.Date, Any); + + +internals.Date.prototype._base = function (value, state, options) { + + var result = { + value: (options.convert && internals.toDate(value, this._flags.format)) || value + }; + + if (result.value instanceof Date && !isNaN(result.value.getTime())) { + result.errors = null; + } + else { + result.errors = Errors.create(internals.isIsoDate(this._flags.format) ? 'date.isoDate' : 'date.base', null, state, options); + } + + return result; +}; + + +internals.toDate = function (value, format) { + + if (value instanceof Date) { + return value; + } + + if (typeof value === 'string' || + Hoek.isInteger(value)) { + + if (typeof value === 'string' && + /^[+-]?\d+$/.test(value)) { + + value = parseInt(value, 10); + } + + var date; + if (format) { + if (internals.isIsoDate(format)) { + date = format.test(value) ? new Date(value) : internals.invalidDate; + } + else { + date = Moment(value, format, true); + date = date.isValid() ? date.toDate() : internals.invalidDate; + } + } + else { + date = new Date(value); + } + + if (!isNaN(date.getTime())) { + return date; + } + } + + return null; +}; + + +internals.compare = function (type, compare) { + + return function (date) { + + var isNow = date === 'now'; + var isRef = Ref.isRef(date); + + if (!isNow && !isRef) { + date = internals.toDate(date); + } + + Hoek.assert(date, 'Invalid date format'); + + return this._test(type, date, function (value, state, options) { + + var compareTo; + if (isNow) { + compareTo = Date.now(); + } + else if (isRef) { + compareTo = internals.toDate(date(state.parent, options)); + + if (!compareTo) { + return Errors.create('date.ref', { ref: date.key }, state, options); + } + + compareTo = compareTo.getTime(); + } + else { + compareTo = date.getTime(); + } + + if (compare(value.getTime(), compareTo)) { + return null; + } + + return Errors.create('date.' + type, { limit: new Date(compareTo) }, state, options); + }); + }; +}; + + +internals.Date.prototype.min = internals.compare('min', function (value, date) { + + return value >= date; +}); + + +internals.Date.prototype.max = internals.compare('max', function (value, date) { + + return value <= date; +}); + + +internals.Date.prototype.format = function (format) { + + Hoek.assert(typeof format === 'string' || (Array.isArray(format) && format.every(function (f) { + + return typeof f === 'string'; + })), 'Invalid format.'); + + var obj = this.clone(); + obj._flags.format = format; + return obj; +}; + +internals.Date.prototype.iso = function () { + + var obj = this.clone(); + obj._flags.format = internals.isoDate; + return obj; +}; + +internals.Date.prototype._isIsoDate = function (value) { + + return internals.isoDate.test(value); +}; + +module.exports = new internals.Date();
@@ -0,0 +1,297 @@
+// Load modules + +var Hoek = require('hoek'); +var Language = require('./language'); + + +// Declare internals + +var internals = {}; + +internals.stringify = function (value, wrapArrays) { + + var type = typeof value; + + if (value === null) { + return 'null'; + } + + if (type === 'string') { + return value; + } + + if (value instanceof internals.Err || type === 'function') { + return value.toString(); + } + + if (type === 'object') { + if (Array.isArray(value)) { + var partial = ''; + + for (var i = 0, il = value.length; i < il; ++i) { + partial += (partial.length ? ', ' : '') + internals.stringify(value[i], wrapArrays); + } + + return wrapArrays ? '[' + partial + ']' : partial; + } + + return value.toString(); + } + + return JSON.stringify(value); +}; + +internals.Err = function (type, context, state, options) { + + this.type = type; + this.context = context || {}; + this.context.key = state.key; + this.path = state.path; + this.options = options; +}; + + +internals.Err.prototype.toString = function () { + + var self = this; + + var localized = this.options.language; + + if (localized.label) { + this.context.key = localized.label; + } + else if (this.context.key === '' || this.context.key === null) { + this.context.key = localized.root || Language.errors.root; + } + + var format = Hoek.reach(localized, this.type) || Hoek.reach(Language.errors, this.type); + var hasKey = /\{\{\!?key\}\}/.test(format); + var skipKey = format.length > 2 && format[0] === '!' && format[1] === '!'; + + if (skipKey) { + format = format.slice(2); + } + + if (!hasKey && !skipKey) { + format = (Hoek.reach(localized, 'key') || Hoek.reach(Language.errors, 'key')) + format; + } + + var wrapArrays = Hoek.reach(localized, 'messages.wrapArrays'); + if (typeof wrapArrays !== 'boolean') { + wrapArrays = Language.errors.messages.wrapArrays; + } + + var message = format.replace(/\{\{(\!?)([^}]+)\}\}/g, function ($0, isSecure, name) { + + var value = Hoek.reach(self.context, name); + var normalized = internals.stringify(value, wrapArrays); + return (isSecure ? Hoek.escapeHtml(normalized) : normalized); + }); + + return message; +}; + + +exports.create = function (type, context, state, options) { + + return new internals.Err(type, context, state, options); +}; + + +exports.process = function (errors, object) { + + if (!errors || !errors.length) { + return null; + } + + // Construct error + + var message = ''; + var details = []; + + var processErrors = function (localErrors, parent) { + + for (var i = 0, il = localErrors.length; i < il; ++i) { + var item = localErrors[i]; + + var detail = { + message: item.toString(), + path: internals.getPath(item), + type: item.type, + context: item.context + }; + + if (!parent) { + message += (message ? '. ' : '') + detail.message; + } + + // Do not push intermediate errors, we're only interested in leafs + if (item.context.reason && item.context.reason.length) { + processErrors(item.context.reason, item.path); + } + else { + details.push(detail); + } + } + }; + + processErrors(errors); + + var error = new Error(message); + error.name = 'ValidationError'; + error.details = details; + error._object = object; + error.annotate = internals.annotate; + return error; +}; + + +internals.getPath = function (item) { + + var recursePath = function (it) { + + var reachedItem = Hoek.reach(it, 'context.reason.0'); + if (reachedItem && reachedItem.context) { + return recursePath(reachedItem); + } + + return it.path; + }; + + return recursePath(item) || item.context.key; +}; + + +// Inspired by json-stringify-safe +internals.safeStringify = function (obj, spaces) { + + return JSON.stringify(obj, internals.serializer(), spaces); +}; + +internals.serializer = function () { + + var cycleReplacer = function (key, value) { + + if (stack[0] === value) { + return '[Circular ~]'; + } + + return '[Circular ~.' + keys.slice(0, stack.indexOf(value)).join('.') + ']'; + }; + + var keys = [], stack = []; + + return function (key, value) { + + if (stack.length > 0) { + var thisPos = stack.indexOf(this); + if (~thisPos) { + stack.length = thisPos + 1; + keys.length = thisPos + 1; + keys[thisPos] = key; + } + else { + stack.push(this); + keys.push(key); + } + + if (~stack.indexOf(value)) { + value = cycleReplacer.call(this, key, value); + } + } + else { + stack.push(value); + } + + if (Array.isArray(value) && value.placeholders) { + var placeholders = value.placeholders; + var arrWithPlaceholders = []; + for (var i = 0, il = value.length; i < il; ++i) { + if (placeholders[i]) { + arrWithPlaceholders.push(placeholders[i]); + } + arrWithPlaceholders.push(value[i]); + } + + value = arrWithPlaceholders; + } + + return value; + }; +}; + + +internals.annotate = function () { + + var obj = Hoek.clone(this._object || {}); + + var lookup = {}; + var el = this.details.length; + for (var e = el - 1; e >= 0; --e) { // Reverse order to process deepest child first + var pos = el - e; + var error = this.details[e]; + var path = error.path.split('.'); + var ref = obj; + for (var i = 0, il = path.length; i < il && ref; ++i) { + var seg = path[i]; + if (i + 1 < il) { + ref = ref[seg]; + } + else { + var value = ref[seg]; + if (Array.isArray(ref)) { + var arrayLabel = '_$idx$_' + (e + 1) + '_$end$_'; + if (!ref.placeholders) { + ref.placeholders = {}; + } + + if (ref.placeholders[seg]) { + ref.placeholders[seg] = ref.placeholders[seg].replace('_$end$_', ', ' + (e + 1) + '_$end$_'); + } + else { + ref.placeholders[seg] = arrayLabel; + } + } else { + if (value !== undefined) { + delete ref[seg]; + var objectLabel = seg + '_$key$_' + pos + '_$end$_'; + ref[objectLabel] = value; + lookup[error.path] = objectLabel; + } + else if (lookup[error.path]) { + var replacement = lookup[error.path]; + var appended = replacement.replace('_$end$_', ', ' + pos + '_$end$_'); + ref[appended] = ref[replacement]; + lookup[error.path] = appended; + delete ref[replacement]; + } + else { + ref['_$miss$_' + seg + '|' + pos + '_$end$_'] = '__missing__'; + } + } + } + } + } + + var message = internals.safeStringify(obj, 2) + .replace(/_\$key\$_([, \d]+)_\$end\$_\"/g, function ($0, $1) { + + return '" \u001b[31m[' + $1 + ']\u001b[0m'; + }).replace(/\"_\$miss\$_([^\|]+)\|(\d+)_\$end\$_\"\: \"__missing__\"/g, function ($0, $1, $2) { + + return '\u001b[41m"' + $1 + '"\u001b[0m\u001b[31m [' + $2 + ']: -- missing --\u001b[0m'; + }).replace(/\s*\"_\$idx\$_([, \d]+)_\$end\$_\",?\n(.*)/g, function ($0, $1, $2) { + + return '\n' + $2 + ' \u001b[31m[' + $1 + ']\u001b[0m'; + }); + + message += '\n\u001b[31m'; + + for (e = 0; e < el; ++e) { + message += '\n[' + (e + 1) + '] ' + this.details[e].message; + } + + message += '\u001b[0m'; + + return message; +};
@@ -0,0 +1,152 @@
+// Load modules + +var Any = require('./any'); +var Cast = require('./cast'); +var Ref = require('./ref'); + + +// Declare internals + +var internals = { + alternatives: require('./alternatives'), + array: require('./array'), + boolean: require('./boolean'), + binary: require('./binary'), + date: require('./date'), + number: require('./number'), + object: require('./object'), + string: require('./string') +}; + + +internals.root = function () { + + var any = new Any(); + + var root = any.clone(); + root.any = function () { + + return any; + }; + + root.alternatives = root.alt = function () { + + return arguments.length ? internals.alternatives.try.apply(internals.alternatives, arguments) : internals.alternatives; + }; + + root.array = function () { + + return internals.array; + }; + + root.boolean = root.bool = function () { + + return internals.boolean; + }; + + root.binary = function () { + + return internals.binary; + }; + + root.date = function () { + + return internals.date; + }; + + root.func = function () { + + return internals.object._func(); + }; + + root.number = function () { + + return internals.number; + }; + + root.object = function () { + + return arguments.length ? internals.object.keys.apply(internals.object, arguments) : internals.object; + }; + + root.string = function () { + + return internals.string; + }; + + root.ref = function () { + + return Ref.create.apply(null, arguments); + }; + + root.isRef = function (ref) { + + return Ref.isRef(ref); + }; + + root.validate = function (value /*, [schema], [options], callback */) { + + var last = arguments[arguments.length - 1]; + var callback = typeof last === 'function' ? last : null; + + var count = arguments.length - (callback ? 1 : 0); + if (count === 1) { + return any.validate(value, callback); + } + + var options = count === 3 ? arguments[2] : {}; + var schema = root.compile(arguments[1]); + + return schema._validateWithOptions(value, options, callback); + }; + + root.describe = function () { + + var schema = arguments.length ? root.compile(arguments[0]) : any; + return schema.describe(); + }; + + root.compile = function (schema) { + + try { + return Cast.schema(schema); + } + catch (err) { + if (err.hasOwnProperty('path')) { + err.message += '(' + err.path + ')'; + } + throw err; + } + }; + + root.assert = function (value, schema, message) { + + root.attempt(value, schema, message); + }; + + root.attempt = function (value, schema, message) { + + var result = root.validate(value, schema); + var error = result.error; + if (error) { + if (!message) { + error.message = error.annotate(); + throw error; + } + + if (!(message instanceof Error)) { + error.message = message + ' ' + error.annotate(); + throw error; + } + + throw message; + } + + return result.value; + }; + + return root; +}; + + +module.exports = internals.root();
@@ -0,0 +1,125 @@
+// Load modules + + +// Declare internals + +var internals = {}; + + +exports.errors = { + root: 'value', + key: '"{{!key}}" ', + messages: { + wrapArrays: true + }, + any: { + unknown: 'is not allowed', + invalid: 'contains an invalid value', + empty: 'is not allowed to be empty', + required: 'is required', + allowOnly: 'must be one of {{valids}}', + default: 'threw an error when running default method' + }, + alternatives: { + base: 'not matching any of the allowed alternatives' + }, + array: { + base: 'must be an array', + includes: 'at position {{pos}} does not match any of the allowed types', + includesSingle: 'single value of "{{!key}}" does not match any of the allowed types', + includesOne: 'at position {{pos}} fails because {{reason}}', + includesOneSingle: 'single value of "{{!key}}" fails because {{reason}}', + includesRequiredUnknowns: 'does not contain {{unknownMisses}} required value(s)', + includesRequiredKnowns: 'does not contain {{knownMisses}}', + includesRequiredBoth: 'does not contain {{knownMisses}} and {{unknownMisses}} other required value(s)', + excludes: 'at position {{pos}} contains an excluded value', + excludesSingle: 'single value of "{{!key}}" contains an excluded value', + min: 'must contain at least {{limit}} items', + max: 'must contain less than or equal to {{limit}} items', + length: 'must contain {{limit}} items', + ordered: 'at position {{pos}} fails because {{reason}}', + orderedLength: 'at position {{pos}} fails because array must contain at most {{limit}} items', + sparse: 'must not be a sparse array', + unique: 'position {{pos}} contains a duplicate value' + }, + boolean: { + base: 'must be a boolean' + }, + binary: { + base: 'must be a buffer or a string', + min: 'must be at least {{limit}} bytes', + max: 'must be less than or equal to {{limit}} bytes', + length: 'must be {{limit}} bytes' + }, + date: { + base: 'must be a number of milliseconds or valid date string', + min: 'must be larger than or equal to "{{limit}}"', + max: 'must be less than or equal to "{{limit}}"', + isoDate: 'must be a valid ISO 8601 date', + ref: 'references "{{ref}}" which is not a date' + }, + function: { + base: 'must be a Function' + }, + object: { + base: 'must be an object', + child: 'child "{{!key}}" fails because {{reason}}', + min: 'must have at least {{limit}} children', + max: 'must have less than or equal to {{limit}} children', + length: 'must have {{limit}} children', + allowUnknown: 'is not allowed', + with: 'missing required peer "{{peer}}"', + without: 'conflict with forbidden peer "{{peer}}"', + missing: 'must contain at least one of {{peers}}', + xor: 'contains a conflict between exclusive peers {{peers}}', + or: 'must contain at least one of {{peers}}', + and: 'contains {{present}} without its required peers {{missing}}', + nand: '!!"{{main}}" must not exist simultaneously with {{peers}}', + assert: '!!"{{ref}}" validation failed because "{{ref}}" failed to {{message}}', + rename: { + multiple: 'cannot rename child "{{from}}" because multiple renames are disabled and another key was already renamed to "{{to}}"', + override: 'cannot rename child "{{from}}" because override is disabled and target "{{to}}" exists' + }, + type: 'must be an instance of "{{type}}"' + }, + number: { + base: 'must be a number', + min: 'must be larger than or equal to {{limit}}', + max: 'must be less than or equal to {{limit}}', + less: 'must be less than {{limit}}', + greater: 'must be greater than {{limit}}', + float: 'must be a float or double', + integer: 'must be an integer', + negative: 'must be a negative number', + positive: 'must be a positive number', + precision: 'must have no more than {{limit}} decimal places', + ref: 'references "{{ref}}" which is not a number', + multiple: 'must be a multiple of {{multiple}}' + }, + string: { + base: 'must be a string', + min: 'length must be at least {{limit}} characters long', + max: 'length must be less than or equal to {{limit}} characters long', + length: 'length must be {{limit}} characters long', + alphanum: 'must only contain alpha-numeric characters', + token: 'must only contain alpha-numeric and underscore characters', + regex: { + base: 'with value "{{!value}}" fails to match the required pattern: {{pattern}}', + name: 'with value "{{!value}}" fails to match the {{name}} pattern' + }, + email: 'must be a valid email', + uri: 'must be a valid uri', + uriCustomScheme: 'must be a valid uri with a scheme matching the {{scheme}} pattern', + isoDate: 'must be a valid ISO 8601 date', + guid: 'must be a valid GUID', + hex: 'must only contain hexadecimal characters', + hostname: 'must be a valid hostname', + lowercase: 'must only contain lowercase characters', + uppercase: 'must only contain uppercase characters', + trim: 'must not have leading or trailing whitespace', + creditCard: 'must be a credit card', + ref: 'references "{{ref}}" which is not a number', + ip: 'must be a valid ip address with a {{cidr}} CIDR', + ipVersion: 'must be a valid ip address of one of the following versions {{version}} with a {{cidr}} CIDR' + } +};
@@ -0,0 +1,184 @@
+// Load modules + +var Any = require('./any'); +var Ref = require('./ref'); +var Errors = require('./errors'); +var Hoek = require('hoek'); + + +// Declare internals + +var internals = {}; + + +internals.Number = function () { + + Any.call(this); + this._type = 'number'; + this._invalids.add(Infinity); + this._invalids.add(-Infinity); +}; + +Hoek.inherits(internals.Number, Any); + +internals.compare = function (type, compare) { + + return function (limit) { + + var isRef = Ref.isRef(limit); + var isNumber = typeof limit === 'number' && !isNaN(limit); + + Hoek.assert(isNumber || isRef, 'limit must be a number or reference'); + + return this._test(type, limit, function (value, state, options) { + + var compareTo; + if (isRef) { + compareTo = limit(state.parent, options); + + if (!(typeof compareTo === 'number' && !isNaN(compareTo))) { + return Errors.create('number.ref', { ref: limit.key }, state, options); + } + } + else { + compareTo = limit; + } + + if (compare(value, compareTo)) { + return null; + } + + return Errors.create('number.' + type, { limit: compareTo, value: value }, state, options); + }); + }; +}; + + +internals.Number.prototype._base = function (value, state, options) { + + var result = { + errors: null, + value: value + }; + + if (typeof value === 'string' && + options.convert) { + + var number = parseFloat(value); + result.value = (isNaN(number) || !isFinite(value)) ? NaN : number; + } + + var isNumber = typeof result.value === 'number' && !isNaN(result.value); + + if (options.convert && 'precision' in this._flags && isNumber) { + + // This is conceptually equivalent to using toFixed but it should be much faster + var precision = Math.pow(10, this._flags.precision); + result.value = Math.round(result.value * precision) / precision; + } + + result.errors = isNumber ? null : Errors.create('number.base', null, state, options); + return result; +}; + + +internals.Number.prototype.min = internals.compare('min', function (value, limit) { + + return value >= limit; +}); + + +internals.Number.prototype.max = internals.compare('max', function (value, limit) { + + return value <= limit; +}); + + +internals.Number.prototype.greater = internals.compare('greater', function (value, limit) { + + return value > limit; +}); + + +internals.Number.prototype.less = internals.compare('less', function (value, limit) { + + return value < limit; +}); + + +internals.Number.prototype.multiple = function (base) { + + Hoek.assert(Hoek.isInteger(base), 'multiple must be an integer'); + Hoek.assert(base > 0, 'multiple must be greater than 0'); + + return this._test('multiple', base, function (value, state, options) { + + if (value % base === 0) { + return null; + } + + return Errors.create('number.multiple', { multiple: base, value: value }, state, options); + }); +}; + + +internals.Number.prototype.integer = function () { + + return this._test('integer', undefined, function (value, state, options) { + + return Hoek.isInteger(value) ? null : Errors.create('number.integer', { value: value }, state, options); + }); +}; + + +internals.Number.prototype.negative = function () { + + return this._test('negative', undefined, function (value, state, options) { + + if (value < 0) { + return null; + } + + return Errors.create('number.negative', { value: value }, state, options); + }); +}; + + +internals.Number.prototype.positive = function () { + + return this._test('positive', undefined, function (value, state, options) { + + if (value > 0) { + return null; + } + + return Errors.create('number.positive', { value: value }, state, options); + }); +}; + + +internals.precisionRx = /(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/; + + +internals.Number.prototype.precision = function (limit) { + + Hoek.assert(Hoek.isInteger(limit), 'limit must be an integer'); + Hoek.assert(!('precision' in this._flags), 'precision already set'); + + var obj = this._test('precision', limit, function (value, state, options){ + + var places = value.toString().match(internals.precisionRx); + var decimals = Math.max((places[1] ? places[1].length : 0) - (places[2] ? parseInt(places[2], 10) : 0), 0); + if (decimals <= limit) { + return null; + } + + return Errors.create('number.precision', { limit: limit, value: value }, state, options); + }); + + obj._flags.precision = limit; + return obj; +}; + + +module.exports = new internals.Number();
@@ -0,0 +1,754 @@
+// Load modules + +var Hoek = require('hoek'); +var Topo = require('topo'); +var Any = require('./any'); +var Cast = require('./cast'); +var Errors = require('./errors'); + + +// Declare internals + +var internals = {}; + + +internals.Object = function () { + + Any.call(this); + this._type = 'object'; + this._inner.children = null; + this._inner.renames = []; + this._inner.dependencies = []; + this._inner.patterns = []; +}; + +Hoek.inherits(internals.Object, Any); + + +internals.Object.prototype._base = function (value, state, options) { + + var item, key, localState, result; + var target = value; + var errors = []; + var finish = function () { + + return { + value: target, + errors: errors.length ? errors : null + }; + }; + + if (typeof value === 'string' && + options.convert) { + + try { + value = JSON.parse(value); + } + catch (parseErr) { } + } + + var type = this._flags.func ? 'function' : 'object'; + if (!value || + typeof value !== type || + Array.isArray(value)) { + + errors.push(Errors.create(type + '.base', null, state, options)); + return finish(); + } + + // Skip if there are no other rules to test + + if (!this._inner.renames.length && + !this._inner.dependencies.length && + !this._inner.children && // null allows any keys + !this._inner.patterns.length) { + + target = value; + return finish(); + } + + // Ensure target is a local copy (parsed) or shallow copy + + if (target === value) { + if (type === 'object') { + target = Object.create(Object.getPrototypeOf(value)); + } + else { + target = function () { + + return value.apply(this, arguments); + }; + + target.prototype = Hoek.clone(value.prototype); + } + + var valueKeys = Object.keys(value); + for (var t = 0, tl = valueKeys.length; t < tl; ++t) { + target[valueKeys[t]] = value[valueKeys[t]]; + } + } + else { + target = value; + } + + // Rename keys + + var renamed = {}; + for (var r = 0, rl = this._inner.renames.length; r < rl; ++r) { + item = this._inner.renames[r]; + + if (item.options.ignoreUndefined && target[item.from] === undefined) { + continue; + } + + if (!item.options.multiple && + renamed[item.to]) { + + errors.push(Errors.create('object.rename.multiple', { from: item.from, to: item.to }, state, options)); + if (options.abortEarly) { + return finish(); + } + } + + if (Object.prototype.hasOwnProperty.call(target, item.to) && + !item.options.override && + !renamed[item.to]) { + + errors.push(Errors.create('object.rename.override', { from: item.from, to: item.to }, state, options)); + if (options.abortEarly) { + return finish(); + } + } + + if (target[item.from] === undefined) { + delete target[item.to]; + } + else { + target[item.to] = target[item.from]; + } + + renamed[item.to] = true; + + if (!item.options.alias) { + delete target[item.from]; + } + } + + // Validate schema + + if (!this._inner.children && // null allows any keys + !this._inner.patterns.length && + !this._inner.dependencies.length) { + + return finish(); + } + + var unprocessed = Hoek.mapToObject(Object.keys(target)); + + if (this._inner.children) { + for (var i = 0, il = this._inner.children.length; i < il; ++i) { + var child = this._inner.children[i]; + key = child.key; + item = target[key]; + + delete unprocessed[key]; + + localState = { key: key, path: (state.path || '') + (state.path && key ? '.' : '') + key, parent: target, reference: state.reference }; + result = child.schema._validate(item, localState, options); + if (result.errors) { + errors.push(Errors.create('object.child', { key: key, reason: result.errors }, localState, options)); + + if (options.abortEarly) { + return finish(); + } + } + + if (child.schema._flags.strip || (result.value === undefined && result.value !== item)) { + delete target[key]; + } + else if (result.value !== undefined) { + target[key] = result.value; + } + } + } + + // Unknown keys + + var unprocessedKeys = Object.keys(unprocessed); + if (unprocessedKeys.length && + this._inner.patterns.length) { + + for (i = 0, il = unprocessedKeys.length; i < il; ++i) { + key = unprocessedKeys[i]; + + for (var p = 0, pl = this._inner.patterns.length; p < pl; ++p) { + var pattern = this._inner.patterns[p]; + + if (pattern.regex.test(key)) { + delete unprocessed[key]; + + item = target[key]; + localState = { key: key, path: (state.path ? state.path + '.' : '') + key, parent: target, reference: state.reference }; + result = pattern.rule._validate(item, localState, options); + if (result.errors) { + errors.push(Errors.create('object.child', { key: key, reason: result.errors }, localState, options)); + + if (options.abortEarly) { + return finish(); + } + } + + if (result.value !== undefined) { + target[key] = result.value; + } + } + } + } + + unprocessedKeys = Object.keys(unprocessed); + } + + if ((this._inner.children || this._inner.patterns.length) && unprocessedKeys.length) { + if (options.stripUnknown || + options.skipFunctions) { + + for (var k = 0, kl = unprocessedKeys.length; k < kl; ++k) { + key = unprocessedKeys[k]; + + if (options.stripUnknown) { + delete target[key]; + delete unprocessed[key]; + } + else if (typeof target[key] === 'function') { + delete unprocessed[key]; + } + } + + unprocessedKeys = Object.keys(unprocessed); + } + + if (unprocessedKeys.length && + (this._flags.allowUnknown !== undefined ? !this._flags.allowUnknown : !options.allowUnknown)) { + + for (var e = 0, el = unprocessedKeys.length; e < el; ++e) { + errors.push(Errors.create('object.allowUnknown', null, { key: unprocessedKeys[e], path: state.path + (state.path ? '.' : '') + unprocessedKeys[e] }, options)); + } + } + } + + // Validate dependencies + + for (var d = 0, dl = this._inner.dependencies.length; d < dl; ++d) { + var dep = this._inner.dependencies[d]; + var err = internals[dep.type](dep.key !== null && value[dep.key], dep.peers, target, { key: dep.key, path: (state.path || '') + (dep.key ? '.' + dep.key : '') }, options); + if (err) { + errors.push(err); + if (options.abortEarly) { + return finish(); + } + } + } + + return finish(); +}; + + +internals.Object.prototype._func = function () { + + var obj = this.clone(); + obj._flags.func = true; + return obj; +}; + + +internals.Object.prototype.keys = function (schema) { + + Hoek.assert(schema === null || schema === undefined || typeof schema === 'object', 'Object schema must be a valid object'); + Hoek.assert(!schema || !schema.isJoi, 'Object schema cannot be a joi schema'); + + var obj = this.clone(); + + if (!schema) { + obj._inner.children = null; + return obj; + } + + var children = Object.keys(schema); + + if (!children.length) { + obj._inner.children = []; + return obj; + } + + var topo = new Topo(); + var child; + if (obj._inner.children) { + for (var i = 0, il = obj._inner.children.length; i < il; ++i) { + child = obj._inner.children[i]; + + // Only add the key if we are not going to replace it later + if (children.indexOf(child.key) === -1) { + topo.add(child, { after: child._refs, group: child.key }); + } + } + } + + for (var c = 0, cl = children.length; c < cl; ++c) { + var key = children[c]; + child = schema[key]; + try { + var cast = Cast.schema(child); + topo.add({ key: key, schema: cast }, { after: cast._refs, group: key }); + } + catch (castErr) { + if (castErr.hasOwnProperty('path')) { + castErr.path = key + '.' + castErr.path; + } + else { + castErr.path = key; + } + throw castErr; + } + } + + obj._inner.children = topo.nodes; + + return obj; +}; + + +internals.Object.prototype.unknown = function (allow) { + + var obj = this.clone(); + obj._flags.allowUnknown = (allow !== false); + return obj; +}; + + +internals.Object.prototype.length = function (limit) { + + Hoek.assert(Hoek.isInteger(limit) && limit >= 0, 'limit must be a positive integer'); + + return this._test('length', limit, function (value, state, options) { + + if (Object.keys(value).length === limit) { + return null; + } + + return Errors.create('object.length', { limit: limit }, state, options); + }); +}; + + +internals.Object.prototype.min = function (limit) { + + Hoek.assert(Hoek.isInteger(limit) && limit >= 0, 'limit must be a positive integer'); + + return this._test('min', limit, function (value, state, options) { + + if (Object.keys(value).length >= limit) { + return null; + } + + return Errors.create('object.min', { limit: limit }, state, options); + }); +}; + + +internals.Object.prototype.max = function (limit) { + + Hoek.assert(Hoek.isInteger(limit) && limit >= 0, 'limit must be a positive integer'); + + return this._test('max', limit, function (value, state, options) { + + if (Object.keys(value).length <= limit) { + return null; + } + + return Errors.create('object.max', { limit: limit }, state, options); + }); +}; + + +internals.Object.prototype.pattern = function (pattern, schema) { + + Hoek.assert(pattern instanceof RegExp, 'Invalid regular expression'); + Hoek.assert(schema !== undefined, 'Invalid rule'); + + pattern = new RegExp(pattern.source, pattern.ignoreCase ? 'i' : undefined); // Future version should break this and forbid unsupported regex flags + + try { + schema = Cast.schema(schema); + } + catch (castErr) { + if (castErr.hasOwnProperty('path')) { + castErr.message += '(' + castErr.path + ')'; + } + + throw castErr; + } + + + var obj = this.clone(); + obj._inner.patterns.push({ regex: pattern, rule: schema }); + return obj; +}; + + +internals.Object.prototype.with = function (key, peers) { + + return this._dependency('with', key, peers); +}; + + +internals.Object.prototype.without = function (key, peers) { + + return this._dependency('without', key, peers); +}; + + +internals.Object.prototype.xor = function () { + + var peers = Hoek.flatten(Array.prototype.slice.call(arguments)); + return this._dependency('xor', null, peers); +}; + + +internals.Object.prototype.or = function () { + + var peers = Hoek.flatten(Array.prototype.slice.call(arguments)); + return this._dependency('or', null, peers); +}; + + +internals.Object.prototype.and = function () { + + var peers = Hoek.flatten(Array.prototype.slice.call(arguments)); + return this._dependency('and', null, peers); +}; + + +internals.Object.prototype.nand = function () { + + var peers = Hoek.flatten(Array.prototype.slice.call(arguments)); + return this._dependency('nand', null, peers); +}; + + +internals.Object.prototype.requiredKeys = function (children) { + + children = Hoek.flatten(Array.prototype.slice.call(arguments)); + return this.applyFunctionToChildren(children, 'required'); +}; + + +internals.Object.prototype.optionalKeys = function (children) { + + children = Hoek.flatten(Array.prototype.slice.call(arguments)); + return this.applyFunctionToChildren(children, 'optional'); +}; + + +internals.renameDefaults = { + alias: false, // Keep old value in place + multiple: false, // Allow renaming multiple keys into the same target + override: false // Overrides an existing key +}; + + +internals.Object.prototype.rename = function (from, to, options) { + + Hoek.assert(typeof from === 'string', 'Rename missing the from argument'); + Hoek.assert(typeof to === 'string', 'Rename missing the to argument'); + Hoek.assert(to !== from, 'Cannot rename key to same name:', from); + + for (var i = 0, il = this._inner.renames.length; i < il; ++i) { + Hoek.assert(this._inner.renames[i].from !== from, 'Cannot rename the same key multiple times'); + } + + var obj = this.clone(); + + obj._inner.renames.push({ + from: from, + to: to, + options: Hoek.applyToDefaults(internals.renameDefaults, options || {}) + }); + + return obj; +}; + + +internals.groupChildren = function (children) { + + children.sort(); + + var grouped = {}; + + for (var c = 0, lc = children.length; c < lc; c++) { + var child = children[c]; + Hoek.assert(typeof child === 'string', 'children must be strings'); + var group = child.split('.')[0]; + var childGroup = grouped[group] = (grouped[group] || []); + childGroup.push(child.substring(group.length + 1)); + } + + return grouped; +}; + + +internals.Object.prototype.applyFunctionToChildren = function (children, fn, args, root) { + + children = [].concat(children); + Hoek.assert(children.length > 0, 'expected at least one children'); + + var groupedChildren = internals.groupChildren(children); + var obj; + + if ('' in groupedChildren) { + obj = this[fn].apply(this, args); + delete groupedChildren['']; + } + else { + obj = this.clone(); + } + + if (obj._inner.children) { + root = root ? (root + '.') : ''; + + for (var i = 0, il = obj._inner.children.length; i < il; ++i) { + var child = obj._inner.children[i]; + var group = groupedChildren[child.key]; + + if (group) { + obj._inner.children[i] = { + key: child.key, + _refs: child._refs, + schema: child.schema.applyFunctionToChildren(group, fn, args, root + child.key) + }; + + delete groupedChildren[child.key]; + } + } + } + + var remaining = Object.keys(groupedChildren); + Hoek.assert(remaining.length === 0, 'unknown key(s)', remaining.join(', ')); + + return obj; +}; + + +internals.Object.prototype._dependency = function (type, key, peers) { + + peers = [].concat(peers); + for (var i = 0, li = peers.length; i < li; i++) { + Hoek.assert(typeof peers[i] === 'string', type, 'peers must be a string or array of strings'); + } + + var obj = this.clone(); + obj._inner.dependencies.push({ type: type, key: key, peers: peers }); + return obj; +}; + + +internals.with = function (value, peers, parent, state, options) { + + if (value === undefined) { + return null; + } + + for (var i = 0, il = peers.length; i < il; ++i) { + var peer = peers[i]; + if (!Object.prototype.hasOwnProperty.call(parent, peer) || + parent[peer] === undefined) { + + return Errors.create('object.with', { peer: peer }, state, options); + } + } + + return null; +}; + + +internals.without = function (value, peers, parent, state, options) { + + if (value === undefined) { + return null; + } + + for (var i = 0, il = peers.length; i < il; ++i) { + var peer = peers[i]; + if (Object.prototype.hasOwnProperty.call(parent, peer) && + parent[peer] !== undefined) { + + return Errors.create('object.without', { peer: peer }, state, options); + } + } + + return null; +}; + + +internals.xor = function (value, peers, parent, state, options) { + + var present = []; + for (var i = 0, il = peers.length; i < il; ++i) { + var peer = peers[i]; + if (Object.prototype.hasOwnProperty.call(parent, peer) && + parent[peer] !== undefined) { + + present.push(peer); + } + } + + if (present.length === 1) { + return null; + } + + if (present.length === 0) { + return Errors.create('object.missing', { peers: peers }, state, options); + } + + return Errors.create('object.xor', { peers: peers }, state, options); +}; + + +internals.or = function (value, peers, parent, state, options) { + + for (var i = 0, il = peers.length; i < il; ++i) { + var peer = peers[i]; + if (Object.prototype.hasOwnProperty.call(parent, peer) && + parent[peer] !== undefined) { + return null; + } + } + + return Errors.create('object.missing', { peers: peers }, state, options); +}; + + +internals.and = function (value, peers, parent, state, options) { + + var missing = []; + var present = []; + var count = peers.length; + for (var i = 0; i < count; ++i) { + var peer = peers[i]; + if (!Object.prototype.hasOwnProperty.call(parent, peer) || + parent[peer] === undefined) { + + missing.push(peer); + } + else { + present.push(peer); + } + } + + var aon = (missing.length === count || present.length === count); + return !aon ? Errors.create('object.and', { present: present, missing: missing }, state, options) : null; +}; + + +internals.nand = function (value, peers, parent, state, options) { + + var present = []; + for (var i = 0, il = peers.length; i < il; ++i) { + var peer = peers[i]; + if (Object.prototype.hasOwnProperty.call(parent, peer) && + parent[peer] !== undefined) { + + present.push(peer); + } + } + + var values = Hoek.clone(peers); + var main = values.splice(0, 1)[0]; + var allPresent = (present.length === peers.length); + return allPresent ? Errors.create('object.nand', { main: main, peers: values }, state, options) : null; +}; + + +internals.Object.prototype.describe = function (shallow) { + + var description = Any.prototype.describe.call(this); + + if (this._inner.children && + !shallow) { + + description.children = {}; + for (var i = 0, il = this._inner.children.length; i < il; ++i) { + var child = this._inner.children[i]; + description.children[child.key] = child.schema.describe(); + } + } + + if (this._inner.dependencies.length) { + description.dependencies = Hoek.clone(this._inner.dependencies); + } + + if (this._inner.patterns.length) { + description.patterns = []; + + for (var p = 0, pl = this._inner.patterns.length; p < pl; ++p) { + var pattern = this._inner.patterns[p]; + description.patterns.push({ regex: pattern.regex.toString(), rule: pattern.rule.describe() }); + } + } + + return description; +}; + + +internals.Object.prototype.assert = function (ref, schema, message) { + + ref = Cast.ref(ref); + Hoek.assert(ref.isContext || ref.depth > 1, 'Cannot use assertions for root level references - use direct key rules instead'); + message = message || 'pass the assertion test'; + + var cast; + try { + cast = Cast.schema(schema); + } + catch (castErr) { + if (castErr.hasOwnProperty('path')) { + castErr.message += '(' + castErr.path + ')'; + } + + throw castErr; + } + + var key = ref.path[ref.path.length - 1]; + var path = ref.path.join('.'); + + return this._test('assert', { cast: cast, ref: ref }, function (value, state, options) { + + var result = cast._validate(ref(value), null, options, value); + if (!result.errors) { + return null; + } + + var localState = Hoek.merge({}, state); + localState.key = key; + localState.path = path; + return Errors.create('object.assert', { ref: localState.path, message: message }, localState, options); + }); +}; + + +internals.Object.prototype.type = function (constructor, name) { + + Hoek.assert(typeof constructor === 'function', 'type must be a constructor function'); + name = name || constructor.name; + + return this._test('type', name, function (value, state, options) { + + if (value instanceof constructor) { + return null; + } + + return Errors.create('object.type', { type: name }, state, options); + }); +}; + + +module.exports = new internals.Object();
@@ -0,0 +1,51 @@
+// Load modules + +var Hoek = require('hoek'); + + +// Declare internals + +var internals = {}; + + +exports.create = function (key, options) { + + Hoek.assert(typeof key === 'string', 'Invalid reference key:', key); + + var settings = Hoek.clone(options); // options can be reused and modified + + var ref = function (value, validationOptions) { + + return Hoek.reach(ref.isContext ? validationOptions.context : value, ref.key, settings); + }; + + ref.isContext = (key[0] === ((settings && settings.contextPrefix) || '$')); + ref.key = (ref.isContext ? key.slice(1) : key); + ref.path = ref.key.split((settings && settings.separator) || '.'); + ref.depth = ref.path.length; + ref.root = ref.path[0]; + ref.isJoi = true; + + ref.toString = function () { + + return (ref.isContext ? 'context:' : 'ref:') + ref.key; + }; + + return ref; +}; + + +exports.isRef = function (ref) { + + return typeof ref === 'function' && ref.isJoi; +}; + + +exports.push = function (array, ref) { + + if (exports.isRef(ref) && + !ref.isContext) { + + array.push(ref.root); + } +};
@@ -0,0 +1,468 @@
+// Load modules + +var Net = require('net'); +var Hoek = require('hoek'); +var Isemail = require('isemail'); +var Any = require('./any'); +var Ref = require('./ref'); +var JoiDate = require('./date'); +var Errors = require('./errors'); +var Uri = require('./string/uri'); +var Ip = require('./string/ip'); + +// Declare internals + +var internals = { + uriRegex: Uri.createUriRegex(), + ipRegex: Ip.createIpRegex(['ipv4', 'ipv6', 'ipvfuture'], 'optional') +}; + +internals.String = function () { + + Any.call(this); + this._type = 'string'; + this._invalids.add(''); +}; + +Hoek.inherits(internals.String, Any); + +internals.compare = function (type, compare) { + + return function (limit, encoding) { + + var isRef = Ref.isRef(limit); + + Hoek.assert((Hoek.isInteger(limit) && limit >= 0) || isRef, 'limit must be a positive integer or reference'); + Hoek.assert(!encoding || Buffer.isEncoding(encoding), 'Invalid encoding:', encoding); + + return this._test(type, limit, function (value, state, options) { + + var compareTo; + if (isRef) { + compareTo = limit(state.parent, options); + + if (!Hoek.isInteger(compareTo)) { + return Errors.create('string.ref', { ref: limit.key }, state, options); + } + } + else { + compareTo = limit; + } + + if (compare(value, compareTo, encoding)) { + return null; + } + + return Errors.create('string.' + type, { limit: compareTo, value: value, encoding: encoding }, state, options); + }); + }; +}; + +internals.String.prototype._base = function (value, state, options) { + + if (typeof value === 'string' && + options.convert) { + + if (this._flags.case) { + value = (this._flags.case === 'upper' ? value.toLocaleUpperCase() : value.toLocaleLowerCase()); + } + + if (this._flags.trim) { + value = value.trim(); + } + + if (this._inner.replacements) { + + for (var r = 0, rl = this._inner.replacements.length; r < rl; ++r) { + var replacement = this._inner.replacements[r]; + value = value.replace(replacement.pattern, replacement.replacement); + } + } + } + + return { + value: value, + errors: (typeof value === 'string') ? null : Errors.create('string.base', { value: value }, state, options) + }; +}; + + +internals.String.prototype.insensitive = function () { + + var obj = this.clone(); + obj._flags.insensitive = true; + return obj; +}; + + +internals.String.prototype.min = internals.compare('min', function (value, limit, encoding) { + + var length = encoding ? Buffer.byteLength(value, encoding) : value.length; + return length >= limit; +}); + + +internals.String.prototype.max = internals.compare('max', function (value, limit, encoding) { + + var length = encoding ? Buffer.byteLength(value, encoding) : value.length; + return length <= limit; +}); + + +internals.String.prototype.creditCard = function () { + + return this._test('creditCard', undefined, function (value, state, options) { + + var i = value.length; + var sum = 0; + var mul = 1; + var char; + + while (i--) { + char = value.charAt(i) * mul; + sum += char - (char > 9) * 9; + mul ^= 3; + } + + var check = (sum % 10 === 0) && (sum > 0); + return check ? null : Errors.create('string.creditCard', { value: value }, state, options); + }); +}; + +internals.String.prototype.length = internals.compare('length', function (value, limit, encoding) { + + var length = encoding ? Buffer.byteLength(value, encoding) : value.length; + return length === limit; +}); + + +internals.String.prototype.regex = function (pattern, name) { + + Hoek.assert(pattern instanceof RegExp, 'pattern must be a RegExp'); + + pattern = new RegExp(pattern.source, pattern.ignoreCase ? 'i' : undefined); // Future version should break this and forbid unsupported regex flags + + return this._test('regex', pattern, function (value, state, options) { + + if (pattern.test(value)) { + return null; + } + + return Errors.create((name ? 'string.regex.name' : 'string.regex.base'), { name: name, pattern: pattern, value: value }, state, options); + }); +}; + + +internals.String.prototype.alphanum = function () { + + return this._test('alphanum', undefined, function (value, state, options) { + + if (/^[a-zA-Z0-9]+$/.test(value)) { + return null; + } + + return Errors.create('string.alphanum', { value: value }, state, options); + }); +}; + + +internals.String.prototype.token = function () { + + return this._test('token', undefined, function (value, state, options) { + + if (/^\w+$/.test(value)) { + return null; + } + + return Errors.create('string.token', { value: value }, state, options); + }); +}; + + +internals.String.prototype.email = function (isEmailOptions) { + + if (isEmailOptions) { + Hoek.assert(typeof isEmailOptions === 'object', 'email options must be an object'); + Hoek.assert(typeof isEmailOptions.checkDNS === 'undefined', 'checkDNS option is not supported'); + Hoek.assert(typeof isEmailOptions.tldWhitelist === 'undefined' || + typeof isEmailOptions.tldWhitelist === 'object', 'tldWhitelist must be an array or object'); + Hoek.assert(typeof isEmailOptions.minDomainAtoms === 'undefined' || + Hoek.isInteger(isEmailOptions.minDomainAtoms) && isEmailOptions.minDomainAtoms > 0, + 'minDomainAtoms must be a positive integer'); + Hoek.assert(typeof isEmailOptions.errorLevel === 'undefined' || typeof isEmailOptions.errorLevel === 'boolean' || + (Hoek.isInteger(isEmailOptions.errorLevel) && isEmailOptions.errorLevel >= 0), + 'errorLevel must be a non-negative integer or boolean'); + } + + return this._test('email', isEmailOptions, function (value, state, options) { + + try { + var result = Isemail(value, isEmailOptions); + if (result === true || result === 0) { + return null; + } + } + catch (e) {} + + return Errors.create('string.email', { value: value }, state, options); + }); +}; + + +internals.String.prototype.ip = function (ipOptions) { + + var regex = internals.ipRegex; + ipOptions = ipOptions || {}; + Hoek.assert(typeof ipOptions === 'object', 'options must be an object'); + + if (ipOptions.cidr) { + Hoek.assert(typeof ipOptions.cidr === 'string', 'cidr must be a string'); + ipOptions.cidr = ipOptions.cidr.toLowerCase(); + + Hoek.assert(ipOptions.cidr in Ip.cidrs, 'cidr must be one of ' + Object.keys(Ip.cidrs).join(', ')); + + // If we only received a `cidr` setting, create a regex for it. But we don't need to create one if `cidr` is "optional" since that is the default + if (!ipOptions.version && ipOptions.cidr !== 'optional') { + regex = Ip.createIpRegex(['ipv4', 'ipv6', 'ipvfuture'], ipOptions.cidr); + } + } + else { + + // Set our default cidr strategy + ipOptions.cidr = 'optional'; + } + + if (ipOptions.version) { + if (!Array.isArray(ipOptions.version)) { + ipOptions.version = [ipOptions.version]; + } + + Hoek.assert(ipOptions.version.length >= 1, 'version must have at least 1 version specified'); + + var versions = []; + for (var i = 0, il = ipOptions.version.length; i < il; ++i) { + var version = ipOptions.version[i]; + Hoek.assert(typeof version === 'string', 'version at position ' + i + ' must be a string'); + version = version.toLowerCase(); + Hoek.assert(Ip.versions[version], 'version at position ' + i + ' must be one of ' + Object.keys(Ip.versions).join(', ')); + versions.push(version); + } + + // Make sure we have a set of versions + versions = Hoek.unique(versions); + + regex = Ip.createIpRegex(versions, ipOptions.cidr); + } + + return this._test('ip', ipOptions, function (value, state, options) { + + if (regex.test(value)) { + return null; + } + + if (versions) { + return Errors.create('string.ipVersion', { value: value, cidr: ipOptions.cidr, version: versions }, state, options); + } + + return Errors.create('string.ip', { value: value, cidr: ipOptions.cidr }, state, options); + }); +}; + + +internals.String.prototype.uri = function (uriOptions) { + + var customScheme = '', + regex = internals.uriRegex; + + if (uriOptions) { + Hoek.assert(typeof uriOptions === 'object', 'options must be an object'); + + if (uriOptions.scheme) { + Hoek.assert(uriOptions.scheme instanceof RegExp || typeof uriOptions.scheme === 'string' || Array.isArray(uriOptions.scheme), 'scheme must be a RegExp, String, or Array'); + + if (!Array.isArray(uriOptions.scheme)) { + uriOptions.scheme = [uriOptions.scheme]; + } + + Hoek.assert(uriOptions.scheme.length >= 1, 'scheme must have at least 1 scheme specified'); + + // Flatten the array into a string to be used to match the schemes. + for (var i = 0, il = uriOptions.scheme.length; i < il; ++i) { + var scheme = uriOptions.scheme[i]; + Hoek.assert(scheme instanceof RegExp || typeof scheme === 'string', 'scheme at position ' + i + ' must be a RegExp or String'); + + // Add OR separators if a value already exists + customScheme += customScheme ? '|' : ''; + + // If someone wants to match HTTP or HTTPS for example then we need to support both RegExp and String so we don't escape their pattern unknowingly. + if (scheme instanceof RegExp) { + customScheme += scheme.source; + } + else { + Hoek.assert(/[a-zA-Z][a-zA-Z0-9+-\.]*/.test(scheme), 'scheme at position ' + i + ' must be a valid scheme'); + customScheme += Hoek.escapeRegex(scheme); + } + } + } + } + + if (customScheme) { + regex = Uri.createUriRegex(customScheme); + } + + return this._test('uri', uriOptions, function (value, state, options) { + + if (regex.test(value)) { + return null; + } + + if (customScheme) { + return Errors.create('string.uriCustomScheme', { scheme: customScheme, value: value }, state, options); + } + + return Errors.create('string.uri', { value: value }, state, options); + }); +}; + + +internals.String.prototype.isoDate = function () { + + return this._test('isoDate', undefined, function (value, state, options) { + + if (JoiDate._isIsoDate(value)) { + return null; + } + + return Errors.create('string.isoDate', { value: value }, state, options); + }); +}; + + +internals.String.prototype.guid = function () { + + var regex = /^[A-F0-9]{8}(?:-?[A-F0-9]{4}){3}-?[A-F0-9]{12}$/i; + var regex2 = /^\{[A-F0-9]{8}(?:-?[A-F0-9]{4}){3}-?[A-F0-9]{12}\}$/i; + + return this._test('guid', undefined, function (value, state, options) { + + if (regex.test(value) || regex2.test(value)) { + return null; + } + + return Errors.create('string.guid', { value: value }, state, options); + }); +}; + + +internals.String.prototype.hex = function () { + + var regex = /^[a-f0-9]+$/i; + + return this._test('hex', regex, function (value, state, options) { + + if (regex.test(value)) { + return null; + } + + return Errors.create('string.hex', { value: value }, state, options); + }); +}; + + +internals.String.prototype.hostname = function () { + + var regex = /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/; + + return this._test('hostname', undefined, function (value, state, options) { + + if ((value.length <= 255 && regex.test(value)) || + Net.isIPv6(value)) { + + return null; + } + + return Errors.create('string.hostname', { value: value }, state, options); + }); +}; + + +internals.String.prototype.lowercase = function () { + + var obj = this._test('lowercase', undefined, function (value, state, options) { + + if (options.convert || + value === value.toLocaleLowerCase()) { + + return null; + } + + return Errors.create('string.lowercase', { value: value }, state, options); + }); + + obj._flags.case = 'lower'; + return obj; +}; + + +internals.String.prototype.uppercase = function () { + + var obj = this._test('uppercase', undefined, function (value, state, options) { + + if (options.convert || + value === value.toLocaleUpperCase()) { + + return null; + } + + return Errors.create('string.uppercase', { value: value }, state, options); + }); + + obj._flags.case = 'upper'; + return obj; +}; + + +internals.String.prototype.trim = function () { + + var obj = this._test('trim', undefined, function (value, state, options) { + + if (options.convert || + value === value.trim()) { + + return null; + } + + return Errors.create('string.trim', { value: value }, state, options); + }); + + obj._flags.trim = true; + return obj; +}; + + +internals.String.prototype.replace = function (pattern, replacement) { + + if (typeof pattern === 'string') { + pattern = new RegExp(Hoek.escapeRegex(pattern), 'g'); + } + + Hoek.assert(pattern instanceof RegExp, 'pattern must be a RegExp'); + Hoek.assert(typeof replacement === 'string', 'replacement must be a String'); + + // This can not be considere a test like trim, we can't "reject" + // anything from this rule, so just clone the current object + var obj = this.clone(); + + if (!obj._inner.replacements) { + obj._inner.replacements = []; + } + + obj._inner.replacements.push({ + pattern: pattern, + replacement: replacement + }); + + return obj; +}; + +module.exports = new internals.String();
@@ -0,0 +1,32 @@
+var RFC3986 = require('./rfc3986'); + +var internals = { + Ip: { + cidrs: { + required: '\\/(?:' + RFC3986.cidr + ')', + optional: '(?:\\/(?:' + RFC3986.cidr + '))?', + forbidden: '' + }, + versions: { + ipv4: RFC3986.IPv4address, + ipv6: RFC3986.IPv6address, + ipvfuture: RFC3986.IPvFuture + } + } +}; + +internals.Ip.createIpRegex = function (versions, cidr) { + + var regex; + for (var i = 0, il = versions.length; i < il; ++i) { + var version = versions[i]; + if (!regex) { + regex = '^(?:' + internals.Ip.versions[version]; + } + regex += '|' + internals.Ip.versions[version]; + } + + return new RegExp(regex + ')' + internals.Ip.cidrs[cidr] + '$'); +}; + +module.exports = internals.Ip;
@@ -0,0 +1,174 @@
+var internals = { + rfc3986: {} +}; + +/** + * elements separated by forward slash ("/") are alternatives. + */ +var or = '|'; + +/** + * DIGIT = %x30-39 ; 0-9 + */ +var digit = '0-9'; +var digitOnly = '[' + digit + ']'; + +/** + * ALPHA = %x41-5A / %x61-7A ; A-Z / a-z + */ +var alpha = 'a-zA-Z'; +var alphaOnly = '[' + alpha + ']'; + +/** + * cidr = DIGIT ; 0-9 + * / %x31-32 DIGIT ; 10-29 + * / "3" %x30-32 ; 30-32 + */ +internals.rfc3986.cidr = digitOnly + or + '[1-2]' + digitOnly + or + '3' + '[0-2]'; + +/** + * HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" + */ +var hexDigit = digit + 'A-Fa-f', + hexDigitOnly = '[' + hexDigit + ']'; + +/** + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + */ +var unreserved = alpha + digit + '-\\._~'; + +/** + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + */ +var subDelims = '!\\$&\'\\(\\)\\*\\+,;='; + +/** + * pct-encoded = "%" HEXDIG HEXDIG + */ +var pctEncoded = '%' + hexDigit; + +/** + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + */ +var pchar = unreserved + pctEncoded + subDelims + ':@'; +var pcharOnly = '[' + pchar + ']'; + +/** + * Rule to support zero-padded addresses. + */ +var zeroPad = '0?'; + +/** + * dec-octet = DIGIT ; 0-9 + * / %x31-39 DIGIT ; 10-99 + * / "1" 2DIGIT ; 100-199 + * / "2" %x30-34 DIGIT ; 200-249 + * / "25" %x30-35 ; 250-255 + */ +var decOctect = '(?:' + zeroPad + zeroPad + digitOnly + or + zeroPad + '[1-9]' + digitOnly + or + '1' + digitOnly + digitOnly + or + '2' + '[0-4]' + digitOnly + or + '25' + '[0-5])'; + +/** + * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet + */ +internals.rfc3986.IPv4address = '(?:' + decOctect + '\\.){3}' + decOctect; + +/** + * h16 = 1*4HEXDIG ; 16 bits of address represented in hexadecimal + * ls32 = ( h16 ":" h16 ) / IPv4address ; least-significant 32 bits of address + * IPv6address = 6( h16 ":" ) ls32 + * / "::" 5( h16 ":" ) ls32 + * / [ h16 ] "::" 4( h16 ":" ) ls32 + * / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 + * / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 + * / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 + * / [ *4( h16 ":" ) h16 ] "::" ls32 + * / [ *5( h16 ":" ) h16 ] "::" h16 + * / [ *6( h16 ":" ) h16 ] "::" + */ +var h16 = hexDigitOnly + '{1,4}'; +var ls32 = '(?:' + h16 + ':' + h16 + '|' + internals.rfc3986.IPv4address + ')'; +var IPv6SixHex = '(?:' + h16 + ':){6}' + ls32; +var IPv6FiveHex = '::(?:' + h16 + ':){5}' + ls32; +var IPv6FourHex = h16 + '::(?:' + h16 + ':){4}' + ls32; +var IPv6ThreeHex = '(?:' + h16 + ':){0,1}' + h16 + '::(?:' + h16 + ':){3}' + ls32; +var IPv6TwoHex = '(?:' + h16 + ':){0,2}' + h16 + '::(?:' + h16 + ':){2}' + ls32; +var IPv6OneHex = '(?:' + h16 + ':){0,3}' + h16 + '::' + h16 + ':' + ls32; +var IPv6NoneHex = '(?:' + h16 + ':){0,4}' + h16 + '::' + ls32; +var IPv6NoneHex2 = '(?:' + h16 + ':){0,5}' + h16 + '::' + h16; +var IPv6NoneHex3 = '(?:' + h16 + ':){0,6}' + h16 + '::'; +internals.rfc3986.IPv6address = '(?:' + IPv6SixHex + or + IPv6FiveHex + or + IPv6FourHex + or + IPv6ThreeHex + or + IPv6TwoHex + or + IPv6OneHex + or + IPv6NoneHex + or + IPv6NoneHex2 + or + IPv6NoneHex3 + ')'; + +/** + * IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) + */ +internals.rfc3986.IPvFuture = 'v' + hexDigitOnly + '+\\.[' + unreserved + subDelims + ':]+'; + +/** + * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + */ +internals.rfc3986.scheme = alphaOnly + '[' + alpha + digit + '+-\\.]*'; + +/** + * userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) + */ +var userinfo = '[' + unreserved + pctEncoded + subDelims + ':]*'; + +/** + * IP-literal = "[" ( IPv6address / IPvFuture ) "]" + */ +var IPLiteral = '\\[(?:' + internals.rfc3986.IPv6address + or + internals.rfc3986.IPvFuture + ')\\]'; + +/** + * reg-name = *( unreserved / pct-encoded / sub-delims ) + */ +var regName = '[' + unreserved + pctEncoded + subDelims + ']{0,255}'; + +/** + * host = IP-literal / IPv4address / reg-name + */ +var host = '(?:' + IPLiteral + or + internals.rfc3986.IPv4address + or + regName + ')'; + +/** + * port = *DIGIT + */ +var port = digitOnly + '*'; + +/** + * authority = [ userinfo "@" ] host [ ":" port ] + */ +var authority = '(?:' + userinfo + '@)?' + host + '(?::' + port + ')?'; + +/** + * segment = *pchar + * segment-nz = 1*pchar + * path = path-abempty ; begins with "/" or is empty + * / path-absolute ; begins with "/" but not "//" + * / path-noscheme ; begins with a non-colon segment + * / path-rootless ; begins with a segment + * / path-empty ; zero characters + * path-abempty = *( "/" segment ) + * path-absolute = "/" [ segment-nz *( "/" segment ) ] + * path-rootless = segment-nz *( "/" segment ) + */ +var segment = pcharOnly + '*'; +var segmentNz = pcharOnly + '+'; +var pathAbEmpty = '(?:\\/' + segment + ')*'; +var pathAbsolute = '\\/(?:' + segmentNz + pathAbEmpty + ')?'; +var pathRootless = segmentNz + pathAbEmpty; + +/** + * hier-part = "//" authority path + */ +internals.rfc3986.hierPart = '(?:\\/\\/' + authority + pathAbEmpty + or + pathAbsolute + or + pathRootless + ')'; + +/** + * query = *( pchar / "/" / "?" ) + */ +internals.rfc3986.query = '[' + pchar + '\\/\\?]*(?=#|$)'; //Finish matching either at the fragment part or end of the line. + +/** + * fragment = *( pchar / "/" / "?" ) + */ +internals.rfc3986.fragment = '[' + pchar + '\\/\\?]*'; + +module.exports = internals.rfc3986;
@@ -0,0 +1,24 @@
+var RFC3986 = require('./rfc3986'); + +var internals = { + Uri: { + createUriRegex: function (optionalScheme) { + + var scheme = RFC3986.scheme; + + // If we were passed a scheme, use it instead of the generic one + if (optionalScheme) { + + // Have to put this in a non-capturing group to handle the OR statements + scheme = '(?:' + optionalScheme + ')'; + } + + /** + * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] + */ + return new RegExp('^' + scheme + ':' + RFC3986.hierPart + '(?:\\?' + RFC3986.query + ')?' + '(?:#' + RFC3986.fragment + ')?$'); + } + } +}; + +module.exports = internals.Uri;
@@ -0,0 +1,18 @@
+.idea +*.iml +npm-debug.log +dump.rdb +node_modules +results.tap +results.xml +npm-shrinkwrap.json +config.json +.DS_Store +*/.DS_Store +*/*/.DS_Store +._* +*/._* +*/*/._* +coverage.* +lib-cov +complexity.md
@@ -0,0 +1,7 @@
+language: node_js + +node_js: + - 0.10 + - 4.0 + +sudo: false
@@ -0,0 +1,1 @@
+Please view our [hapijs contributing guide](https://github.com/hapijs/hapi/blob/master/CONTRIBUTING.md).
@@ -0,0 +1,31 @@
+Copyright (c) 2011-2014, Walmart and other contributors. +Copyright (c) 2011, Yahoo Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The names of any contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * * * + +The complete list of contributors can be found at: https://github.com/hapijs/hapi/graphs/contributors +Portions of this project were initially based on the Yahoo! Inc. Postmile project, +published at https://github.com/yahoo/postmile.
@@ -0,0 +1,584 @@
+ + +Utility methods for the hapi ecosystem. This module is not intended to solve every problem for everyone, but rather as a central place to store hapi-specific methods. If you're looking for a general purpose utility module, check out [lodash](https://github.com/lodash/lodash) or [underscore](https://github.com/jashkenas/underscore). + +[](http://travis-ci.org/hapijs/hoek) + +Lead Maintainer: [Nathan LaFreniere](https://github.com/nlf) + +# Table of Contents + +* [Introduction](#introduction "Introduction") +* [Object](#object "Object") + * [clone](#cloneobj "clone") + * [cloneWithShallow](#clonewithshallowobj-keys "cloneWithShallow") + * [merge](#mergetarget-source-isnulloverride-ismergearrays "merge") + * [applyToDefaults](#applytodefaultsdefaults-options-isnulloverride "applyToDefaults") + * [applyToDefaultsWithShallow](#applytodefaultswithshallowdefaults-options-keys "applyToDefaultsWithShallow") + * [deepEqual](#deepequala-b "deepEqual") + * [unique](#uniquearray-key "unique") + * [mapToObject](#maptoobjectarray-key "mapToObject") + * [intersect](#intersectarray1-array2 "intersect") + * [contain](#containref-values-options "contain") + * [flatten](#flattenarray-target "flatten") + * [reach](#reachobj-chain-options "reach") + * [reachTemplate](#reachtemplateobj-template-options "reachTemplate") + * [transform](#transformobj-transform-options "transform") + * [shallow](#shallowobj "shallow") + * [stringify](#stringifyobj "stringify") +* [Timer](#timer "Timer") +* [Bench](#bench "Bench") +* [Binary Encoding/Decoding](#binary-encodingdecoding "Binary Encoding/Decoding") + * [base64urlEncode](#base64urlencodevalue "binary64urlEncode") + * [base64urlDecode](#base64urldecodevalue "binary64urlDecode") +* [Escaping Characters](#escaping-characters "Escaping Characters") + * [escapeHtml](#escapehtmlstring "escapeHtml") + * [escapeHeaderAttribute](#escapeheaderattributeattribute "escapeHeaderAttribute") + * [escapeRegex](#escaperegexstring "escapeRegex") +* [Errors](#errors "Errors") + * [assert](#assertcondition-message "assert") + * [abort](#abortmessage "abort") + * [displayStack](#displaystackslice "displayStack") + * [callStack](#callstackslice "callStack") +* [Function](#function "Function") + * [nextTick](#nexttickfn "nextTick") + * [once](#oncefn "once") + * [ignore](#ignore "ignore") +* [Miscellaneous](#miscellaneous "Miscellaneous") + * [uniqueFilename](#uniquefilenamepath-extension "uniqueFilename") + * [isAbsolutePath](#isabsolutepathpath-platform "isAbsolutePath") + * [isInteger](#isintegervalue "isInteger") + + + +# Introduction + +The *Hoek* library contains some common functions used within the hapi ecosystem. It comes with useful methods for Arrays (clone, merge, applyToDefaults), Objects (removeKeys, copy), Asserting and more. + +For example, to use Hoek to set configuration with default options: +```javascript +var Hoek = require('hoek'); + +var default = {url : "www.github.com", port : "8000", debug : true}; + +var config = Hoek.applyToDefaults(default, {port : "3000", admin : true}); + +// In this case, config would be { url: 'www.github.com', port: '3000', debug: true, admin: true } +``` + +Under each of the sections (such as Array), there are subsections which correspond to Hoek methods. Each subsection will explain how to use the corresponding method. In each js excerpt below, the `var Hoek = require('hoek');` is omitted for brevity. + +## Object + +Hoek provides several helpful methods for objects and arrays. + +### clone(obj) + +This method is used to clone an object or an array. A *deep copy* is made (duplicates everything, including values that are objects, as well as non-enumerable properties). + +```javascript + +var nestedObj = { + w: /^something$/ig, + x: { + a: [1, 2, 3], + b: 123456, + c: new Date() + }, + y: 'y', + z: new Date() + }; + +var copy = Hoek.clone(nestedObj); + +copy.x.b = 100; + +console.log(copy.y); // results in 'y' +console.log(nestedObj.x.b); // results in 123456 +console.log(copy.x.b); // results in 100 +``` + +### cloneWithShallow(obj, keys) +keys is an array of key names to shallow copy + +This method is also used to clone an object or array, however any keys listed in the `keys` array are shallow copied while those not listed are deep copied. + +```javascript + +var nestedObj = { + w: /^something$/ig, + x: { + a: [1, 2, 3], + b: 123456, + c: new Date() + }, + y: 'y', + z: new Date() + }; + +var copy = Hoek.cloneWithShallow(nestedObj, ['x']); + +copy.x.b = 100; + +console.log(copy.y); // results in 'y' +console.log(nestedObj.x.b); // results in 100 +console.log(copy.x.b); // results in 100 +``` + +### merge(target, source, isNullOverride, isMergeArrays) +isNullOverride, isMergeArrays default to true + +Merge all the properties of source into target, source wins in conflict, and by default null and undefined from source are applied. +Merge is destructive where the target is modified. For non destructive merge, use `applyToDefaults`. + + +```javascript + +var target = {a: 1, b : 2}; +var source = {a: 0, c: 5}; +var source2 = {a: null, c: 5}; + +Hoek.merge(target, source); // results in {a: 0, b: 2, c: 5} +Hoek.merge(target, source2); // results in {a: null, b: 2, c: 5} +Hoek.merge(target, source2, false); // results in {a: 1, b: 2, c: 5} + +var targetArray = [1, 2, 3]; +var sourceArray = [4, 5]; + +Hoek.merge(targetArray, sourceArray); // results in [1, 2, 3, 4, 5] +Hoek.merge(targetArray, sourceArray, true, false); // results in [4, 5] +``` + +### applyToDefaults(defaults, options, isNullOverride) +isNullOverride defaults to false + +Apply options to a copy of the defaults + +```javascript + +var defaults = { host: "localhost", port: 8000 }; +var options = { port: 8080 }; + +var config = Hoek.applyToDefaults(defaults, options); // results in { host: "localhost", port: 8080 } +``` + +Apply options with a null value to a copy of the defaults + +```javascript + +var defaults = { host: "localhost", port: 8000 }; +var options = { host: null, port: 8080 }; + +var config = Hoek.applyToDefaults(defaults, options, true); // results in { host: null, port: 8080 } +``` + +### applyToDefaultsWithShallow(defaults, options, keys) +keys is an array of key names to shallow copy + +Apply options to a copy of the defaults. Keys specified in the last parameter are shallow copied from options instead of merged. + +```javascript + +var defaults = { + server: { + host: "localhost", + port: 8000 + }, + name: 'example' + }; + +var options = { server: { port: 8080 } }; + +var config = Hoek.applyToDefaultsWithShallow(defaults, options, ['server']); // results in { server: { port: 8080 }, name: 'example' } +``` + +### deepEqual(b, a, [options]) + +Performs a deep comparison of the two values including support for circular dependencies, prototype, and properties. To skip prototype comparisons, use `options.prototype = false` + +```javascript +Hoek.deepEqual({ a: [1, 2], b: 'string', c: { d: true } }, { a: [1, 2], b: 'string', c: { d: true } }); //results in true +Hoek.deepEqual(Object.create(null), {}, { prototype: false }); //results in true +Hoek.deepEqual(Object.create(null), {}); //results in false +``` + +### unique(array, key) + +Remove duplicate items from Array + +```javascript + +var array = [1, 2, 2, 3, 3, 4, 5, 6]; + +var newArray = Hoek.unique(array); // results in [1,2,3,4,5,6] + +array = [{id: 1}, {id: 1}, {id: 2}]; + +newArray = Hoek.unique(array, "id"); // results in [{id: 1}, {id: 2}] +``` + +### mapToObject(array, key) + +Convert an Array into an Object + +```javascript + +var array = [1,2,3]; +var newObject = Hoek.mapToObject(array); // results in [{"1": true}, {"2": true}, {"3": true}] + +array = [{id: 1}, {id: 2}]; +newObject = Hoek.mapToObject(array, "id"); // results in [{"id": 1}, {"id": 2}] +``` + +### intersect(array1, array2) + +Find the common unique items in two arrays + +```javascript + +var array1 = [1, 2, 3]; +var array2 = [1, 4, 5]; + +var newArray = Hoek.intersect(array1, array2); // results in [1] +``` + +### contain(ref, values, [options]) + +Tests if the reference value contains the provided values where: +- `ref` - the reference string, array, or object. +- `values` - a single or array of values to find within the `ref` value. If `ref` is an object, `values` can be a key name, + an array of key names, or an object with key-value pairs to compare. +- `options` - an optional object with the following optional settings: + - `deep` - if `true`, performed a deep comparison of the values. + - `once` - if `true`, allows only one occurrence of each value. + - `only` - if `true`, does not allow values not explicitly listed. + - `part` - if `true`, allows partial match of the values (at least one must always match). + +Note: comparing a string to overlapping values will result in failed comparison (e.g. `contain('abc', ['ab', 'bc'])`). +Also, if an object key's value does not match the provided value, `false` is returned even when `part` is specified. + +```javascript +Hoek.contain('aaa', 'a', { only: true }); // true +Hoek.contain([{ a: 1 }], [{ a: 1 }], { deep: true }); // true +Hoek.contain([1, 2, 2], [1, 2], { once: true }); // false +Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, d: 4 }, { part: true }); // true +``` + +### flatten(array, [target]) + +Flatten an array + +```javascript + +var array = [1, [2, 3]]; + +var flattenedArray = Hoek.flatten(array); // results in [1, 2, 3] + +array = [1, [2, 3]]; +target = [4, [5]]; + +flattenedArray = Hoek.flatten(array, target); // results in [4, [5], 1, 2, 3] +``` + +### reach(obj, chain, [options]) + +Converts an object key chain string to reference + +- `options` - optional settings + - `separator` - string to split chain path on, defaults to '.' + - `default` - value to return if the path or value is not present, default is `undefined` + - `strict` - if `true`, will throw an error on missing member, default is `false` + - `functions` - if `true` allow traversing functions for properties. `false` will throw an error if a function is part of the chain. + +A chain including negative numbers will work like negative indices on an +array. + +If chain is `null`, `undefined` or `false`, the object itself will be returned. + +```javascript + +var chain = 'a.b.c'; +var obj = {a : {b : { c : 1}}}; + +Hoek.reach(obj, chain); // returns 1 + +var chain = 'a.b.-1'; +var obj = {a : {b : [2,3,6]}}; + +Hoek.reach(obj, chain); // returns 6 +``` + +### reachTemplate(obj, template, [options]) + +Replaces string parameters (`{name}`) with their corresponding object key values by applying the +(`reach()`)[#reachobj-chain-options] method where: + +- `obj` - the context object used for key lookup. +- `template` - a string containing `{}` parameters. +- `options` - optional (`reach()`)[#reachobj-chain-options] options. + +```javascript + +var chain = 'a.b.c'; +var obj = {a : {b : { c : 1}}}; + +Hoek.reachTemplate(obj, '1+{a.b.c}=2'); // returns '1+1=2' +``` + +### transform(obj, transform, [options]) + +Transforms an existing object into a new one based on the supplied `obj` and `transform` map. `options` are the same as the `reach` options. The first argument can also be an array of objects. In that case the method will return an array of transformed objects. + +```javascript +var source = { + address: { + one: '123 main street', + two: 'PO Box 1234' + }, + title: 'Warehouse', + state: 'CA' +}; + +var result = Hoek.transform(source, { + 'person.address.lineOne': 'address.one', + 'person.address.lineTwo': 'address.two', + 'title': 'title', + 'person.address.region': 'state' +}); +// Results in +// { +// person: { +// address: { +// lineOne: '123 main street', +// lineTwo: 'PO Box 1234', +// region: 'CA' +// } +// }, +// title: 'Warehouse' +// } +``` + +### shallow(obj) + +Performs a shallow copy by copying the references of all the top level children where: +- `obj` - the object to be copied. + +```javascript +var shallow = Hoek.shallow({ a: { b: 1 } }); +``` + +### stringify(obj) + +Converts an object to string using the built-in `JSON.stringify()` method with the difference that any errors are caught +and reported back in the form of the returned string. Used as a shortcut for displaying information to the console (e.g. in +error message) without the need to worry about invalid conversion. + +```javascript +var a = {}; +a.b = a; +Hoek.stringify(a); // Returns '[Cannot display object: Converting circular structure to JSON]' +``` + +# Timer + +A Timer object. Initializing a new timer object sets the ts to the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC. + +```javascript + +var timerObj = new Hoek.Timer(); +console.log("Time is now: " + timerObj.ts); +console.log("Elapsed time from initialization: " + timerObj.elapsed() + 'milliseconds'); +``` + + +# Bench + +Same as Timer with the exception that `ts` stores the internal node clock which is not related to `Date.now()` and cannot be used to display +human-readable timestamps. More accurate for benchmarking or internal timers. + +# Binary Encoding/Decoding + +### base64urlEncode(value) + +Encodes value in Base64 or URL encoding + +### base64urlDecode(value) + +Decodes data in Base64 or URL encoding. +# Escaping Characters + +Hoek provides convenient methods for escaping html characters. The escaped characters are as followed: + +```javascript + +internals.htmlEscaped = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`' +}; +``` + +### escapeHtml(string) + +```javascript + +var string = '<html> hey </html>'; +var escapedString = Hoek.escapeHtml(string); // returns <html> hey </html> +``` + +### escapeHeaderAttribute(attribute) + +Escape attribute value for use in HTTP header + +```javascript + +var a = Hoek.escapeHeaderAttribute('I said "go w\\o me"'); //returns I said \"go w\\o me\" +``` + + +### escapeRegex(string) + +Escape string for Regex construction + +```javascript + +var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,'); // returns 4\^f\$s\.4\*5\+\-_\?%\=#\!\:@\|~\\\/`"\(>\)\[<\]d\{\}s\, +``` + +# Errors + +### assert(condition, message) + +```javascript + +var a = 1, b = 2; + +Hoek.assert(a === b, 'a should equal b'); // Throws 'a should equal b' +``` + +Note that you may also pass an already created Error object as the second parameter, and `assert` will throw that object. + +```javascript + +var a = 1, b = 2; + +Hoek.assert(a === b, new Error('a should equal b')); // Throws the given error object +``` + +### abort(message) + +First checks if `process.env.NODE_ENV === 'test'`, and if so, throws error message. Otherwise, +displays most recent stack and then exits process. + + + +### displayStack(slice) + +Displays the trace stack + +```javascript + +var stack = Hoek.displayStack(); +console.log(stack); // returns something like: + +[ 'null (/Users/user/Desktop/hoek/test.js:4:18)', + 'Module._compile (module.js:449:26)', + 'Module._extensions..js (module.js:467:10)', + 'Module.load (module.js:356:32)', + 'Module._load (module.js:312:12)', + 'Module.runMain (module.js:492:10)', + 'startup.processNextTick.process._tickCallback (node.js:244:9)' ] +``` + +### callStack(slice) + +Returns a trace stack array. + +```javascript + +var stack = Hoek.callStack(); +console.log(stack); // returns something like: + +[ [ '/Users/user/Desktop/hoek/test.js', 4, 18, null, false ], + [ 'module.js', 449, 26, 'Module._compile', false ], + [ 'module.js', 467, 10, 'Module._extensions..js', false ], + [ 'module.js', 356, 32, 'Module.load', false ], + [ 'module.js', 312, 12, 'Module._load', false ], + [ 'module.js', 492, 10, 'Module.runMain', false ], + [ 'node.js', + 244, + 9, + 'startup.processNextTick.process._tickCallback', + false ] ] +``` + +## Function + +### nextTick(fn) + +Returns a new function that wraps `fn` in `process.nextTick`. + +```javascript + +var myFn = function () { + console.log('Do this later'); +}; + +var nextFn = Hoek.nextTick(myFn); + +nextFn(); +console.log('Do this first'); + +// Results in: +// +// Do this first +// Do this later +``` + +### once(fn) + +Returns a new function that can be run multiple times, but makes sure `fn` is only run once. + +```javascript + +var myFn = function () { + console.log('Ran myFn'); +}; + +var onceFn = Hoek.once(myFn); +onceFn(); // results in "Ran myFn" +onceFn(); // results in undefined +``` + +### ignore + +A simple no-op function. It does nothing at all. + +## Miscellaneous + +### uniqueFilename(path, extension) +`path` to prepend with the randomly generated file name. `extension` is the optional file extension, defaults to `''`. + +Returns a randomly generated file name at the specified `path`. The result is a fully resolved path to a file. + +```javascript +var result = Hoek.uniqueFilename('./test/modules', 'txt'); // results in "full/path/test/modules/{random}.txt" +``` + +### isAbsolutePath(path, [platform]) + +Determines whether `path` is an absolute path. Returns `true` or `false`. + +- `path` - A file path to test for whether it is absolute or not. +- `platform` - An optional parameter used for specifying the platform. Defaults to `process.platform`. + +### isInteger(value) + +Check `value` to see if it is an integer. Returns true/false. + +```javascript +var result = Hoek.isInteger('23') +```
@@ -0,0 +1,132 @@
+// Declare internals + +var internals = {}; + + +exports.escapeJavaScript = function (input) { + + if (!input) { + return ''; + } + + var escaped = ''; + + for (var i = 0, il = input.length; i < il; ++i) { + + var charCode = input.charCodeAt(i); + + if (internals.isSafe(charCode)) { + escaped += input[i]; + } + else { + escaped += internals.escapeJavaScriptChar(charCode); + } + } + + return escaped; +}; + + +exports.escapeHtml = function (input) { + + if (!input) { + return ''; + } + + var escaped = ''; + + for (var i = 0, il = input.length; i < il; ++i) { + + var charCode = input.charCodeAt(i); + + if (internals.isSafe(charCode)) { + escaped += input[i]; + } + else { + escaped += internals.escapeHtmlChar(charCode); + } + } + + return escaped; +}; + + +internals.escapeJavaScriptChar = function (charCode) { + + if (charCode >= 256) { + return '\\u' + internals.padLeft('' + charCode, 4); + } + + var hexValue = new Buffer(String.fromCharCode(charCode), 'ascii').toString('hex'); + return '\\x' + internals.padLeft(hexValue, 2); +}; + + +internals.escapeHtmlChar = function (charCode) { + + var namedEscape = internals.namedHtml[charCode]; + if (typeof namedEscape !== 'undefined') { + return namedEscape; + } + + if (charCode >= 256) { + return '&#' + charCode + ';'; + } + + var hexValue = new Buffer(String.fromCharCode(charCode), 'ascii').toString('hex'); + return '&#x' + internals.padLeft(hexValue, 2) + ';'; +}; + + +internals.padLeft = function (str, len) { + + while (str.length < len) { + str = '0' + str; + } + + return str; +}; + + +internals.isSafe = function (charCode) { + + return (typeof internals.safeCharCodes[charCode] !== 'undefined'); +}; + + +internals.namedHtml = { + '38': '&', + '60': '<', + '62': '>', + '34': '"', + '160': ' ', + '162': '¢', + '163': '£', + '164': '¤', + '169': '©', + '174': '®' +}; + + +internals.safeCharCodes = (function () { + + var safe = {}; + + for (var i = 32; i < 123; ++i) { + + if ((i >= 97) || // a-z + (i >= 65 && i <= 90) || // A-Z + (i >= 48 && i <= 57) || // 0-9 + i === 32 || // space + i === 46 || // . + i === 44 || // , + i === 45 || // - + i === 58 || // : + i === 95) { // _ + + safe[i] = null; + } + } + + return safe; +}());
@@ -0,0 +1,993 @@
+// Load modules + +var Crypto = require('crypto'); +var Path = require('path'); +var Util = require('util'); +var Escape = require('./escape'); + + +// Declare internals + +var internals = {}; + + +// Clone object or array + +exports.clone = function (obj, seen) { + + if (typeof obj !== 'object' || + obj === null) { + + return obj; + } + + seen = seen || { orig: [], copy: [] }; + + var lookup = seen.orig.indexOf(obj); + if (lookup !== -1) { + return seen.copy[lookup]; + } + + var newObj; + var cloneDeep = false; + + if (!Array.isArray(obj)) { + if (Buffer.isBuffer(obj)) { + newObj = new Buffer(obj); + } + else if (obj instanceof Date) { + newObj = new Date(obj.getTime()); + } + else if (obj instanceof RegExp) { + newObj = new RegExp(obj); + } + else { + var proto = Object.getPrototypeOf(obj); + if (proto && + proto.isImmutable) { + + newObj = obj; + } + else { + newObj = Object.create(proto); + cloneDeep = true; + } + } + } + else { + newObj = []; + cloneDeep = true; + } + + seen.orig.push(obj); + seen.copy.push(newObj); + + if (cloneDeep) { + var keys = Object.getOwnPropertyNames(obj); + for (var i = 0, il = keys.length; i < il; ++i) { + var key = keys[i]; + var descriptor = Object.getOwnPropertyDescriptor(obj, key); + if (descriptor && + (descriptor.get || + descriptor.set)) { + + Object.defineProperty(newObj, key, descriptor); + } + else { + newObj[key] = exports.clone(obj[key], seen); + } + } + } + + return newObj; +}; + + +// Merge all the properties of source into target, source wins in conflict, and by default null and undefined from source are applied +/*eslint-disable */ +exports.merge = function (target, source, isNullOverride /* = true */, isMergeArrays /* = true */) { +/*eslint-enable */ + exports.assert(target && typeof target === 'object', 'Invalid target value: must be an object'); + exports.assert(source === null || source === undefined || typeof source === 'object', 'Invalid source value: must be null, undefined, or an object'); + + if (!source) { + return target; + } + + if (Array.isArray(source)) { + exports.assert(Array.isArray(target), 'Cannot merge array onto an object'); + if (isMergeArrays === false) { // isMergeArrays defaults to true + target.length = 0; // Must not change target assignment + } + + for (var i = 0, il = source.length; i < il; ++i) { + target.push(exports.clone(source[i])); + } + + return target; + } + + var keys = Object.keys(source); + for (var k = 0, kl = keys.length; k < kl; ++k) { + var key = keys[k]; + var value = source[key]; + if (value && + typeof value === 'object') { + + if (!target[key] || + typeof target[key] !== 'object' || + (Array.isArray(target[key]) ^ Array.isArray(value)) || + value instanceof Date || + Buffer.isBuffer(value) || + value instanceof RegExp) { + + target[key] = exports.clone(value); + } + else { + exports.merge(target[key], value, isNullOverride, isMergeArrays); + } + } + else { + if (value !== null && + value !== undefined) { // Explicit to preserve empty strings + + target[key] = value; + } + else if (isNullOverride !== false) { // Defaults to true + target[key] = value; + } + } + } + + return target; +}; + + +// Apply options to a copy of the defaults + +exports.applyToDefaults = function (defaults, options, isNullOverride) { + + exports.assert(defaults && typeof defaults === 'object', 'Invalid defaults value: must be an object'); + exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object'); + + if (!options) { // If no options, return null + return null; + } + + var copy = exports.clone(defaults); + + if (options === true) { // If options is set to true, use defaults + return copy; + } + + return exports.merge(copy, options, isNullOverride === true, false); +}; + + +// Clone an object except for the listed keys which are shallow copied + +exports.cloneWithShallow = function (source, keys) { + + if (!source || + typeof source !== 'object') { + + return source; + } + + var storage = internals.store(source, keys); // Move shallow copy items to storage + var copy = exports.clone(source); // Deep copy the rest + internals.restore(copy, source, storage); // Shallow copy the stored items and restore + return copy; +}; + + +internals.store = function (source, keys) { + + var storage = {}; + for (var i = 0, il = keys.length; i < il; ++i) { + var key = keys[i]; + var value = exports.reach(source, key); + if (value !== undefined) { + storage[key] = value; + internals.reachSet(source, key, undefined); + } + } + + return storage; +}; + + +internals.restore = function (copy, source, storage) { + + var keys = Object.keys(storage); + for (var i = 0, il = keys.length; i < il; ++i) { + var key = keys[i]; + internals.reachSet(copy, key, storage[key]); + internals.reachSet(source, key, storage[key]); + } +}; + + +internals.reachSet = function (obj, key, value) { + + var path = key.split('.'); + var ref = obj; + for (var i = 0, il = path.length; i < il; ++i) { + var segment = path[i]; + if (i + 1 === il) { + ref[segment] = value; + } + + ref = ref[segment]; + } +}; + + +// Apply options to defaults except for the listed keys which are shallow copied from option without merging + +exports.applyToDefaultsWithShallow = function (defaults, options, keys) { + + exports.assert(defaults && typeof defaults === 'object', 'Invalid defaults value: must be an object'); + exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object'); + exports.assert(keys && Array.isArray(keys), 'Invalid keys'); + + if (!options) { // If no options, return null + return null; + } + + var copy = exports.cloneWithShallow(defaults, keys); + + if (options === true) { // If options is set to true, use defaults + return copy; + } + + var storage = internals.store(options, keys); // Move shallow copy items to storage + exports.merge(copy, options, false, false); // Deep copy the rest + internals.restore(copy, options, storage); // Shallow copy the stored items and restore + return copy; +}; + + +// Deep object or array comparison + +exports.deepEqual = function (obj, ref, options, seen) { + + options = options || { prototype: true }; + + var type = typeof obj; + + if (type !== typeof ref) { + return false; + } + + if (type !== 'object' || + obj === null || + ref === null) { + + if (obj === ref) { // Copied from Deep-eql, copyright(c) 2013 Jake Luer, jake@alogicalparadox.com, MIT Licensed, https://github.com/chaijs/deep-eql + return obj !== 0 || 1 / obj === 1 / ref; // -0 / +0 + } + + return obj !== obj && ref !== ref; // NaN + } + + seen = seen || []; + if (seen.indexOf(obj) !== -1) { + return true; // If previous comparison failed, it would have stopped execution + } + + seen.push(obj); + + if (Array.isArray(obj)) { + if (!Array.isArray(ref)) { + return false; + } + + if (!options.part && obj.length !== ref.length) { + return false; + } + + for (var i = 0, il = obj.length; i < il; ++i) { + if (options.part) { + var found = false; + for (var r = 0, rl = ref.length; r < rl; ++r) { + if (exports.deepEqual(obj[i], ref[r], options, seen)) { + found = true; + break; + } + } + + return found; + } + + if (!exports.deepEqual(obj[i], ref[i], options, seen)) { + return false; + } + } + + return true; + } + + if (Buffer.isBuffer(obj)) { + if (!Buffer.isBuffer(ref)) { + return false; + } + + if (obj.length !== ref.length) { + return false; + } + + for (var j = 0, jl = obj.length; j < jl; ++j) { + if (obj[j] !== ref[j]) { + return false; + } + } + + return true; + } + + if (obj instanceof Date) { + return (ref instanceof Date && obj.getTime() === ref.getTime()); + } + + if (obj instanceof RegExp) { + return (ref instanceof RegExp && obj.toString() === ref.toString()); + } + + if (options.prototype) { + if (Object.getPrototypeOf(obj) !== Object.getPrototypeOf(ref)) { + return false; + } + } + + var keys = Object.getOwnPropertyNames(obj); + + if (!options.part && keys.length !== Object.getOwnPropertyNames(ref).length) { + return false; + } + + for (var k = 0, kl = keys.length; k < kl; ++k) { + var key = keys[k]; + var descriptor = Object.getOwnPropertyDescriptor(obj, key); + if (descriptor.get) { + if (!exports.deepEqual(descriptor, Object.getOwnPropertyDescriptor(ref, key), options, seen)) { + return false; + } + } + else if (!exports.deepEqual(obj[key], ref[key], options, seen)) { + return false; + } + } + + return true; +}; + + +// Remove duplicate items from array + +exports.unique = function (array, key) { + + var index = {}; + var result = []; + + for (var i = 0, il = array.length; i < il; ++i) { + var id = (key ? array[i][key] : array[i]); + if (index[id] !== true) { + + result.push(array[i]); + index[id] = true; + } + } + + return result; +}; + + +// Convert array into object + +exports.mapToObject = function (array, key) { + + if (!array) { + return null; + } + + var obj = {}; + for (var i = 0, il = array.length; i < il; ++i) { + if (key) { + if (array[i][key]) { + obj[array[i][key]] = true; + } + } + else { + obj[array[i]] = true; + } + } + + return obj; +}; + + +// Find the common unique items in two arrays + +exports.intersect = function (array1, array2, justFirst) { + + if (!array1 || !array2) { + return []; + } + + var common = []; + var hash = (Array.isArray(array1) ? exports.mapToObject(array1) : array1); + var found = {}; + for (var i = 0, il = array2.length; i < il; ++i) { + if (hash[array2[i]] && !found[array2[i]]) { + if (justFirst) { + return array2[i]; + } + + common.push(array2[i]); + found[array2[i]] = true; + } + } + + return (justFirst ? null : common); +}; + + +// Test if the reference contains the values + +exports.contain = function (ref, values, options) { + + /* + string -> string(s) + array -> item(s) + object -> key(s) + object -> object (key:value) + */ + + var valuePairs = null; + if (typeof ref === 'object' && + typeof values === 'object' && + !Array.isArray(ref) && + !Array.isArray(values)) { + + valuePairs = values; + values = Object.keys(values); + } + else { + values = [].concat(values); + } + + options = options || {}; // deep, once, only, part + + exports.assert(arguments.length >= 2, 'Insufficient arguments'); + exports.assert(typeof ref === 'string' || typeof ref === 'object', 'Reference must be string or an object'); + exports.assert(values.length, 'Values array cannot be empty'); + + var compare, compareFlags; + if (options.deep) { + compare = exports.deepEqual; + + var hasOnly = options.hasOwnProperty('only'), hasPart = options.hasOwnProperty('part'); + + compareFlags = { + prototype: hasOnly ? options.only : hasPart ? !options.part : false, + part: hasOnly ? !options.only : hasPart ? options.part : true + }; + } + else { + compare = function (a, b) { + + return a === b; + }; + } + + var misses = false; + var matches = new Array(values.length); + for (var i = 0, il = matches.length; i < il; ++i) { + matches[i] = 0; + } + + if (typeof ref === 'string') { + var pattern = '('; + for (i = 0, il = values.length; i < il; ++i) { + var value = values[i]; + exports.assert(typeof value === 'string', 'Cannot compare string reference to non-string value'); + pattern += (i ? '|' : '') + exports.escapeRegex(value); + } + + var regex = new RegExp(pattern + ')', 'g'); + var leftovers = ref.replace(regex, function ($0, $1) { + + var index = values.indexOf($1); + ++matches[index]; + return ''; // Remove from string + }); + + misses = !!leftovers; + } + else if (Array.isArray(ref)) { + for (i = 0, il = ref.length; i < il; ++i) { + for (var j = 0, jl = values.length, matched = false; j < jl && matched === false; ++j) { + matched = compare(values[j], ref[i], compareFlags) && j; + } + + if (matched !== false) { + ++matches[matched]; + } + else { + misses = true; + } + } + } + else { + var keys = Object.keys(ref); + for (i = 0, il = keys.length; i < il; ++i) { + var key = keys[i]; + var pos = values.indexOf(key); + if (pos !== -1) { + if (valuePairs && + !compare(valuePairs[key], ref[key], compareFlags)) { + + return false; + } + + ++matches[pos]; + } + else { + misses = true; + } + } + } + + var result = false; + for (i = 0, il = matches.length; i < il; ++i) { + result = result || !!matches[i]; + if ((options.once && matches[i] > 1) || + (!options.part && !matches[i])) { + + return false; + } + } + + if (options.only && + misses) { + + return false; + } + + return result; +}; + + +// Flatten array + +exports.flatten = function (array, target) { + + var result = target || []; + + for (var i = 0, il = array.length; i < il; ++i) { + if (Array.isArray(array[i])) { + exports.flatten(array[i], result); + } + else { + result.push(array[i]); + } + } + + return result; +}; + + +// Convert an object key chain string ('a.b.c') to reference (object[a][b][c]) + +exports.reach = function (obj, chain, options) { + + if (chain === false || + chain === null || + typeof chain === 'undefined') { + + return obj; + } + + options = options || {}; + if (typeof options === 'string') { + options = { separator: options }; + } + + var path = chain.split(options.separator || '.'); + var ref = obj; + for (var i = 0, il = path.length; i < il; ++i) { + var key = path[i]; + if (key[0] === '-' && Array.isArray(ref)) { + key = key.slice(1, key.length); + key = ref.length - key; + } + + if (!ref || + !ref.hasOwnProperty(key) || + (typeof ref !== 'object' && options.functions === false)) { // Only object and function can have properties + + exports.assert(!options.strict || i + 1 === il, 'Missing segment', key, 'in reach path ', chain); + exports.assert(typeof ref === 'object' || options.functions === true || typeof ref !== 'function', 'Invalid segment', key, 'in reach path ', chain); + ref = options.default; + break; + } + + ref = ref[key]; + } + + return ref; +}; + + +exports.reachTemplate = function (obj, template, options) { + + return template.replace(/{([^}]+)}/g, function ($0, chain) { + + var value = exports.reach(obj, chain, options); + return (value === undefined || value === null ? '' : value); + }); +}; + + +exports.formatStack = function (stack) { + + var trace = []; + for (var i = 0, il = stack.length; i < il; ++i) { + var item = stack[i]; + trace.push([item.getFileName(), item.getLineNumber(), item.getColumnNumber(), item.getFunctionName(), item.isConstructor()]); + } + + return trace; +}; + + +exports.formatTrace = function (trace) { + + var display = []; + + for (var i = 0, il = trace.length; i < il; ++i) { + var row = trace[i]; + display.push((row[4] ? 'new ' : '') + row[3] + ' (' + row[0] + ':' + row[1] + ':' + row[2] + ')'); + } + + return display; +}; + + +exports.callStack = function (slice) { + + // http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi + + var v8 = Error.prepareStackTrace; + Error.prepareStackTrace = function (err, stack) { + + return stack; + }; + + var capture = {}; + Error.captureStackTrace(capture, arguments.callee); /*eslint no-caller:0 */ + var stack = capture.stack; + + Error.prepareStackTrace = v8; + + var trace = exports.formatStack(stack); + + if (slice) { + return trace.slice(slice); + } + + return trace; +}; + + +exports.displayStack = function (slice) { + + var trace = exports.callStack(slice === undefined ? 1 : slice + 1); + + return exports.formatTrace(trace); +}; + + +exports.abortThrow = false; + + +exports.abort = function (message, hideStack) { + + if (process.env.NODE_ENV === 'test' || exports.abortThrow === true) { + throw new Error(message || 'Unknown error'); + } + + var stack = ''; + if (!hideStack) { + stack = exports.displayStack(1).join('\n\t'); + } + console.log('ABORT: ' + message + '\n\t' + stack); + process.exit(1); +}; + + +exports.assert = function (condition /*, msg1, msg2, msg3 */) { + + if (condition) { + return; + } + + if (arguments.length === 2 && arguments[1] instanceof Error) { + throw arguments[1]; + } + + var msgs = []; + for (var i = 1, il = arguments.length; i < il; ++i) { + if (arguments[i] !== '') { + msgs.push(arguments[i]); // Avoids Array.slice arguments leak, allowing for V8 optimizations + } + } + + msgs = msgs.map(function (msg) { + + return typeof msg === 'string' ? msg : msg instanceof Error ? msg.message : exports.stringify(msg); + }); + throw new Error(msgs.join(' ') || 'Unknown error'); +}; + + +exports.Timer = function () { + + this.ts = 0; + this.reset(); +}; + + +exports.Timer.prototype.reset = function () { + + this.ts = Date.now(); +}; + + +exports.Timer.prototype.elapsed = function () { + + return Date.now() - this.ts; +}; + + +exports.Bench = function () { + + this.ts = 0; + this.reset(); +}; + + +exports.Bench.prototype.reset = function () { + + this.ts = exports.Bench.now(); +}; + + +exports.Bench.prototype.elapsed = function () { + + return exports.Bench.now() - this.ts; +}; + + +exports.Bench.now = function () { + + var ts = process.hrtime(); + return (ts[0] * 1e3) + (ts[1] / 1e6); +}; + + +// Escape string for Regex construction + +exports.escapeRegex = function (string) { + + // Escape ^$.*+-?=!:|\/()[]{}, + return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&'); +}; + + +// Base64url (RFC 4648) encode + +exports.base64urlEncode = function (value, encoding) { + + var buf = (Buffer.isBuffer(value) ? value : new Buffer(value, encoding || 'binary')); + return buf.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, ''); +}; + + +// Base64url (RFC 4648) decode + +exports.base64urlDecode = function (value, encoding) { + + if (value && + !/^[\w\-]*$/.test(value)) { + + return new Error('Invalid character'); + } + + try { + var buf = new Buffer(value, 'base64'); + return (encoding === 'buffer' ? buf : buf.toString(encoding || 'binary')); + } + catch (err) { + return err; + } +}; + + +// Escape attribute value for use in HTTP header + +exports.escapeHeaderAttribute = function (attribute) { + + // Allowed value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9, \, " + + exports.assert(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/.test(attribute), 'Bad attribute value (' + attribute + ')'); + + return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"'); // Escape quotes and slash +}; + + +exports.escapeHtml = function (string) { + + return Escape.escapeHtml(string); +}; + + +exports.escapeJavaScript = function (string) { + + return Escape.escapeJavaScript(string); +}; + + +exports.nextTick = function (callback) { + + return function () { + + var args = arguments; + process.nextTick(function () { + + callback.apply(null, args); + }); + }; +}; + + +exports.once = function (method) { + + if (method._hoekOnce) { + return method; + } + + var once = false; + var wrapped = function () { + + if (!once) { + once = true; + method.apply(null, arguments); + } + }; + + wrapped._hoekOnce = true; + + return wrapped; +}; + + +exports.isAbsolutePath = function (path, platform) { + + if (!path) { + return false; + } + + if (Path.isAbsolute) { // node >= 0.11 + return Path.isAbsolute(path); + } + + platform = platform || process.platform; + + // Unix + + if (platform !== 'win32') { + return path[0] === '/'; + } + + // Windows + + return !!/^(?:[a-zA-Z]:[\\\/])|(?:[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/])/.test(path); // C:\ or \\something\something +}; + + +exports.isInteger = function (value) { + + return (typeof value === 'number' && + parseFloat(value) === parseInt(value, 10) && + !isNaN(value)); +}; + + +exports.ignore = function () { }; + + +exports.inherits = Util.inherits; + + +exports.format = Util.format; + + +exports.transform = function (source, transform, options) { + + exports.assert(source === null || source === undefined || typeof source === 'object' || Array.isArray(source), 'Invalid source object: must be null, undefined, an object, or an array'); + + if (Array.isArray(source)) { + var results = []; + for (var i = 0, il = source.length; i < il; ++i) { + results.push(exports.transform(source[i], transform, options)); + } + return results; + } + + var result = {}; + var keys = Object.keys(transform); + + for (var k = 0, kl = keys.length; k < kl; ++k) { + var key = keys[k]; + var path = key.split('.'); + var sourcePath = transform[key]; + + exports.assert(typeof sourcePath === 'string', 'All mappings must be "." delineated strings'); + + var segment; + var res = result; + + while (path.length > 1) { + segment = path.shift(); + if (!res[segment]) { + res[segment] = {}; + } + res = res[segment]; + } + segment = path.shift(); + res[segment] = exports.reach(source, sourcePath, options); + } + + return result; +}; + + +exports.uniqueFilename = function (path, extension) { + + if (extension) { + extension = extension[0] !== '.' ? '.' + extension : extension; + } + else { + extension = ''; + } + + path = Path.resolve(path); + var name = [Date.now(), process.pid, Crypto.randomBytes(8).toString('hex')].join('-') + extension; + return Path.join(path, name); +}; + + +exports.stringify = function () { + + try { + return JSON.stringify.apply(null, arguments); + } + catch (err) { + return '[Cannot display object: ' + err.message + ']'; + } +}; + + +exports.shallow = function (source) { + + var target = {}; + var keys = Object.keys(source); + for (var i = 0, il = keys.length; i < il; ++i) { + var key = keys[i]; + target[key] = source[key]; + } + + return target; +};
@@ -0,0 +1,61 @@
+{ + "name": "hoek", + "description": "General purpose node utilities", + "version": "2.16.3", + "repository": { + "type": "git", + "url": "git://github.com/hapijs/hoek.git" + }, + "main": "lib/index.js", + "keywords": [ + "utilities" + ], + "engines": { + "node": ">=0.10.40" + }, + "dependencies": {}, + "devDependencies": { + "code": "1.x.x", + "lab": "5.x.x" + }, + "scripts": { + "test": "lab -a code -t 100 -L", + "test-cov-html": "lab -a code -t 100 -L -r html -o coverage.html" + }, + "license": "BSD-3-Clause", + "gitHead": "20f36e85616264d4b73a64a374803175213a9121", + "bugs": { + "url": "https://github.com/hapijs/hoek/issues" + }, + "homepage": "https://github.com/hapijs/hoek#readme", + "_id": "hoek@2.16.3", + "_shasum": "20bb7403d3cea398e91dc4710a8ff1b8274a25ed", + "_from": "hoek@>=2.0.0 <3.0.0", + "_npmVersion": "3.3.3", + "_nodeVersion": "4.1.0", + "_npmUser": { + "name": "nlf", + "email": "quitlahok@gmail.com" + }, + "dist": { + "shasum": "20bb7403d3cea398e91dc4710a8ff1b8274a25ed", + "tarball": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" + }, + "maintainers": [ + { + "name": "hueniverse", + "email": "eran@hueniverse.com" + }, + { + "name": "wyatt", + "email": "wpreul@gmail.com" + }, + { + "name": "nlf", + "email": "quitlahok@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,88 @@
+// Load modules + +var Code = require('code'); +var Hoek = require('../lib'); +var Lab = require('lab'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.experiment; +var it = lab.test; +var expect = Code.expect; + + +describe('escapeJavaScript()', function () { + + it('encodes / characters', function (done) { + + var encoded = Hoek.escapeJavaScript('<script>alert(1)</script>'); + expect(encoded).to.equal('\\x3cscript\\x3ealert\\x281\\x29\\x3c\\x2fscript\\x3e'); + done(); + }); + + it('encodes \' characters', function (done) { + + var encoded = Hoek.escapeJavaScript('something(\'param\')'); + expect(encoded).to.equal('something\\x28\\x27param\\x27\\x29'); + done(); + }); + + it('encodes large unicode characters with the correct padding', function (done) { + + var encoded = Hoek.escapeJavaScript(String.fromCharCode(500) + String.fromCharCode(1000)); + expect(encoded).to.equal('\\u0500\\u1000'); + done(); + }); + + it('doesn\'t throw an exception when passed null', function (done) { + + var encoded = Hoek.escapeJavaScript(null); + expect(encoded).to.equal(''); + done(); + }); +}); + +describe('escapeHtml()', function () { + + it('encodes / characters', function (done) { + + var encoded = Hoek.escapeHtml('<script>alert(1)</script>'); + expect(encoded).to.equal('<script>alert(1)</script>'); + done(); + }); + + it('encodes < and > as named characters', function (done) { + + var encoded = Hoek.escapeHtml('<script><>'); + expect(encoded).to.equal('<script><>'); + done(); + }); + + it('encodes large unicode characters', function (done) { + + var encoded = Hoek.escapeHtml(String.fromCharCode(500) + String.fromCharCode(1000)); + expect(encoded).to.equal('ǴϨ'); + done(); + }); + + it('doesn\'t throw an exception when passed null', function (done) { + + var encoded = Hoek.escapeHtml(null); + expect(encoded).to.equal(''); + done(); + }); + + it('encodes {} characters', function (done) { + + var encoded = Hoek.escapeHtml('{}'); + expect(encoded).to.equal('{}'); + done(); + }); +});
@@ -0,0 +1,2513 @@
+// Load modules + +var Fs = require('fs'); +var Path = require('path'); +var Code = require('code'); +var Hoek = require('../lib'); +var Lab = require('lab'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.experiment; +var it = lab.test; +var expect = Code.expect; + + +var nestedObj = { + v: [7, 8, 9], + w: /^something$/igm, + x: { + a: [1, 2, 3], + b: 123456, + c: new Date(), + d: /hi/igm, + e: /hello/ + }, + y: 'y', + z: new Date(1378775452757) +}; + +var dupsArray = [nestedObj, { z: 'z' }, nestedObj]; +var reducedDupsArray = [nestedObj, { z: 'z' }]; + +describe('clone()', function () { + + it('clones a nested object', function (done) { + + var a = nestedObj; + var b = Hoek.clone(a); + + expect(a).to.deep.equal(b); + expect(a.z.getTime()).to.equal(b.z.getTime()); + done(); + }); + + it('clones a null object', function (done) { + + var b = Hoek.clone(null); + + expect(b).to.equal(null); + done(); + }); + + it('should not convert undefined properties to null', function (done) { + + var obj = { something: undefined }; + var b = Hoek.clone(obj); + + expect(typeof b.something).to.equal('undefined'); + done(); + }); + + it('should not throw on circular reference', function (done) { + + var a = {}; + a.x = a; + + var test = function () { + + var b = Hoek.clone(a); + }; + + expect(test).to.not.throw(); + done(); + }); + + it('clones circular reference', function (done) { + + var x = { + 'z': new Date() + }; + x.y = x; + + var b = Hoek.clone(x); + expect(Object.keys(b.y)).to.deep.equal(Object.keys(x)); + expect(b.z).to.not.equal(x.z); + expect(b.y).to.not.equal(x.y); + expect(b.y.z).to.not.equal(x.y.z); + expect(b.y).to.equal(b); + expect(b.y.y.y.y).to.equal(b); + done(); + }); + + it('clones an object with a null prototype', function (done) { + + var obj = Object.create(null); + var b = Hoek.clone(obj); + + expect(b).to.deep.equal(obj); + done(); + }); + + it('clones deeply nested object', function (done) { + + var a = { + x: { + y: { + a: [1, 2, 3], + b: 123456, + c: new Date(), + d: /hi/igm, + e: /hello/ + } + } + }; + + var b = Hoek.clone(a); + + expect(a).to.deep.equal(b); + expect(a.x.y.c.getTime()).to.equal(b.x.y.c.getTime()); + done(); + }); + + it('clones arrays', function (done) { + + var a = [1, 2, 3]; + + var b = Hoek.clone(a); + + expect(a).to.deep.equal(b); + done(); + }); + + it('performs actual copy for shallow keys (no pass by reference)', function (done) { + + var x = Hoek.clone(nestedObj); + var y = Hoek.clone(nestedObj); + + // Date + expect(x.z).to.not.equal(nestedObj.z); + expect(x.z).to.not.equal(y.z); + + // Regex + expect(x.w).to.not.equal(nestedObj.w); + expect(x.w).to.not.equal(y.w); + + // Array + expect(x.v).to.not.equal(nestedObj.v); + expect(x.v).to.not.equal(y.v); + + // Immutable(s) + x.y = 5; + expect(x.y).to.not.equal(nestedObj.y); + expect(x.y).to.not.equal(y.y); + + done(); + }); + + it('performs actual copy for deep keys (no pass by reference)', function (done) { + + var x = Hoek.clone(nestedObj); + var y = Hoek.clone(nestedObj); + + expect(x.x.c).to.not.equal(nestedObj.x.c); + expect(x.x.c).to.not.equal(y.x.c); + + expect(x.x.c.getTime()).to.equal(nestedObj.x.c.getTime()); + expect(x.x.c.getTime()).to.equal(y.x.c.getTime()); + done(); + }); + + it('copies functions with properties', function (done) { + + var a = { + x: function () { + + return 1; + }, + y: {} + }; + a.x.z = 'string in function'; + a.x.v = function () { + + return 2; + }; + a.y.u = a.x; + + var b = Hoek.clone(a); + expect(b.x()).to.equal(1); + expect(b.x.v()).to.equal(2); + expect(b.y.u).to.equal(b.x); + expect(b.x.z).to.equal('string in function'); + done(); + }); + + it('should copy a buffer', function (done) { + + var tls = { + key: new Buffer([1, 2, 3, 4, 5]), + cert: new Buffer([1, 2, 3, 4, 5, 6, 10]) + }; + + var copiedTls = Hoek.clone(tls); + expect(Buffer.isBuffer(copiedTls.key)).to.equal(true); + expect(JSON.stringify(copiedTls.key)).to.equal(JSON.stringify(tls.key)); + expect(Buffer.isBuffer(copiedTls.cert)).to.equal(true); + expect(JSON.stringify(copiedTls.cert)).to.equal(JSON.stringify(tls.cert)); + done(); + }); + + it('clones an object with a prototype', function (done) { + + var Obj = function () { + + this.a = 5; + }; + + Obj.prototype.b = function () { + + return 'c'; + }; + + var a = new Obj(); + var b = Hoek.clone(a); + + expect(b.a).to.equal(5); + expect(b.b()).to.equal('c'); + expect(a).to.deep.equal(b); + done(); + }); + + it('reuses cloned Date object', function (done) { + + var obj = { + a: new Date() + }; + + obj.b = obj.a; + + var copy = Hoek.clone(obj); + expect(copy.a).to.equal(copy.b); + done(); + }); + + it('shallow copies an object with a prototype and isImmutable flag', function (done) { + + var Obj = function () { + + this.value = 5; + }; + + Obj.prototype.b = function () { + + return 'c'; + }; + + Obj.prototype.isImmutable = true; + + var obj = { + a: new Obj() + }; + + var copy = Hoek.clone(obj); + + expect(obj.a.value).to.equal(5); + expect(copy.a.value).to.equal(5); + expect(copy.a.b()).to.equal('c'); + expect(obj.a).to.equal(copy.a); + done(); + }); + + it('clones an object with property getter without executing it', function (done) { + + var obj = {}; + var value = 1; + var execCount = 0; + + Object.defineProperty(obj, 'test', { + enumerable: true, + configurable: true, + get: function () { + + ++execCount; + return value; + } + }); + + var copy = Hoek.clone(obj); + expect(execCount).to.equal(0); + expect(copy.test).to.equal(1); + expect(execCount).to.equal(1); + done(); + }); + + it('clones an object with property getter and setter', function (done) { + + var obj = { + _test: 0 + }; + + Object.defineProperty(obj, 'test', { + enumerable: true, + configurable: true, + get: function () { + + return this._test; + }, + set: function (value) { + + this._test = value - 1; + } + }); + + var copy = Hoek.clone(obj); + expect(copy.test).to.equal(0); + copy.test = 5; + expect(copy.test).to.equal(4); + done(); + }); + + it('clones an object with only property setter', function (done) { + + var obj = { + _test: 0 + }; + + Object.defineProperty(obj, 'test', { + enumerable: true, + configurable: true, + set: function (value) { + + this._test = value - 1; + } + }); + + var copy = Hoek.clone(obj); + expect(copy._test).to.equal(0); + copy.test = 5; + expect(copy._test).to.equal(4); + done(); + }); + + it('clones an object with non-enumerable properties', function (done) { + + var obj = { + _test: 0 + }; + + Object.defineProperty(obj, 'test', { + enumerable: false, + configurable: true, + set: function (value) { + + this._test = value - 1; + } + }); + + var copy = Hoek.clone(obj); + expect(copy._test).to.equal(0); + copy.test = 5; + expect(copy._test).to.equal(4); + done(); + }); + + it('clones an object where getOwnPropertyDescriptor returns undefined', function (done) { + + var oldGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + var obj = { a: 'b' }; + Object.getOwnPropertyDescriptor = function () { + + return undefined; + }; + + var copy = Hoek.clone(obj); + Object.getOwnPropertyDescriptor = oldGetOwnPropertyDescriptor; + expect(copy).to.deep.equal(obj); + done(); + }); +}); + +describe('merge()', function () { + + it('deep copies source items', function (done) { + + var target = { + b: 3, + d: [] + }; + + var source = { + c: { + d: 1 + }, + d: [{ e: 1 }] + }; + + Hoek.merge(target, source); + expect(target.c).to.not.equal(source.c); + expect(target.c).to.deep.equal(source.c); + expect(target.d).to.not.equal(source.d); + expect(target.d[0]).to.not.equal(source.d[0]); + expect(target.d).to.deep.equal(source.d); + done(); + }); + + it('merges array over an object', function (done) { + + var a = { + x: ['n', 'm'] + }; + + var b = { + x: { + n: '1', + m: '2' + } + }; + + Hoek.merge(b, a); + expect(a.x[0]).to.equal('n'); + expect(a.x.n).to.not.exist(); + done(); + }); + + it('merges object over an array', function (done) { + + var a = { + x: ['n', 'm'] + }; + + var b = { + x: { + n: '1', + m: '2' + } + }; + + Hoek.merge(a, b); + expect(a.x.n).to.equal('1'); + expect(a.x[0]).to.not.exist(); + done(); + }); + + it('does not throw if source is null', function (done) { + + var a = {}; + var b = null; + var c = null; + + expect(function () { + + c = Hoek.merge(a, b); + }).to.not.throw(); + + expect(c).to.equal(a); + done(); + }); + + it('does not throw if source is undefined', function (done) { + + var a = {}; + var b; + var c = null; + + expect(function () { + + c = Hoek.merge(a, b); + }).to.not.throw(); + + expect(c).to.equal(a); + done(); + }); + + it('throws if source is not an object', function (done) { + + expect(function () { + + var a = {}; + var b = 0; + + Hoek.merge(a, b); + }).to.throw('Invalid source value: must be null, undefined, or an object'); + done(); + }); + + it('throws if target is not an object', function (done) { + + expect(function () { + + var a = 0; + var b = {}; + + Hoek.merge(a, b); + }).to.throw('Invalid target value: must be an object'); + done(); + }); + + it('throws if target is not an array and source is', function (done) { + + expect(function () { + + var a = {}; + var b = [1, 2]; + + Hoek.merge(a, b); + }).to.throw('Cannot merge array onto an object'); + done(); + }); + + it('returns the same object when merging arrays', function (done) { + + var a = []; + var b = [1, 2]; + + expect(Hoek.merge(a, b)).to.equal(a); + done(); + }); + + it('combines an empty object with a non-empty object', function (done) { + + var a = {}; + var b = nestedObj; + + var c = Hoek.merge(a, b); + expect(a).to.deep.equal(b); + expect(c).to.deep.equal(b); + done(); + }); + + it('overrides values in target', function (done) { + + var a = { x: 1, y: 2, z: 3, v: 5, t: 'test', m: 'abc' }; + var b = { x: null, z: 4, v: 0, t: { u: 6 }, m: '123' }; + + var c = Hoek.merge(a, b); + expect(c.x).to.equal(null); + expect(c.y).to.equal(2); + expect(c.z).to.equal(4); + expect(c.v).to.equal(0); + expect(c.m).to.equal('123'); + expect(c.t).to.deep.equal({ u: 6 }); + done(); + }); + + it('overrides values in target (flip)', function (done) { + + var a = { x: 1, y: 2, z: 3, v: 5, t: 'test', m: 'abc' }; + var b = { x: null, z: 4, v: 0, t: { u: 6 }, m: '123' }; + + var d = Hoek.merge(b, a); + expect(d.x).to.equal(1); + expect(d.y).to.equal(2); + expect(d.z).to.equal(3); + expect(d.v).to.equal(5); + expect(d.m).to.equal('abc'); + expect(d.t).to.deep.equal('test'); + done(); + }); + + it('retains Date properties', function (done) { + + var a = { x: new Date(1378776452757) }; + + var b = Hoek.merge({}, a); + expect(a.x.getTime()).to.equal(b.x.getTime()); + done(); + }); + + it('retains Date properties when merging keys', function (done) { + + var a = { x: new Date(1378776452757) }; + + var b = Hoek.merge({ x: {} }, a); + expect(a.x.getTime()).to.equal(b.x.getTime()); + done(); + }); + + it('overrides Buffer', function (done) { + + var a = { x: new Buffer('abc') }; + + var b = Hoek.merge({ x: {} }, a); + expect(a.x.toString()).to.equal('abc'); + done(); + }); +}); + +describe('applyToDefaults()', function () { + + var defaults = { + a: 1, + b: 2, + c: { + d: 3, + e: [5, 6] + }, + f: 6, + g: 'test' + }; + + it('throws when target is null', function (done) { + + expect(function () { + + Hoek.applyToDefaults(null, {}); + }).to.throw('Invalid defaults value: must be an object'); + done(); + }); + + it('returns null if options is false', function (done) { + + var result = Hoek.applyToDefaults(defaults, false); + expect(result).to.equal(null); + done(); + }); + + it('returns null if options is null', function (done) { + + var result = Hoek.applyToDefaults(defaults, null); + expect(result).to.equal(null); + done(); + }); + + it('returns null if options is undefined', function (done) { + + var result = Hoek.applyToDefaults(defaults, undefined); + expect(result).to.equal(null); + done(); + }); + + it('returns a copy of defaults if options is true', function (done) { + + var result = Hoek.applyToDefaults(defaults, true); + expect(result).to.deep.equal(defaults); + done(); + }); + + it('applies object to defaults', function (done) { + + var obj = { + a: null, + c: { + e: [4] + }, + f: 0, + g: { + h: 5 + } + }; + + var result = Hoek.applyToDefaults(defaults, obj); + expect(result.c.e).to.deep.equal([4]); + expect(result.a).to.equal(1); + expect(result.b).to.equal(2); + expect(result.f).to.equal(0); + expect(result.g).to.deep.equal({ h: 5 }); + done(); + }); + + it('applies object to defaults with null', function (done) { + + var obj = { + a: null, + c: { + e: [4] + }, + f: 0, + g: { + h: 5 + } + }; + + var result = Hoek.applyToDefaults(defaults, obj, true); + expect(result.c.e).to.deep.equal([4]); + expect(result.a).to.equal(null); + expect(result.b).to.equal(2); + expect(result.f).to.equal(0); + expect(result.g).to.deep.equal({ h: 5 }); + done(); + }); +}); + +describe('cloneWithShallow()', function () { + + it('deep clones except for listed keys', function (done) { + + var source = { + a: { + b: 5 + }, + c: { + d: 6 + } + }; + + var copy = Hoek.cloneWithShallow(source, ['c']); + expect(copy).to.deep.equal(source); + expect(copy).to.not.equal(source); + expect(copy.a).to.not.equal(source.a); + expect(copy.b).to.equal(source.b); + done(); + }); + + it('returns immutable value', function (done) { + + expect(Hoek.cloneWithShallow(5)).to.equal(5); + done(); + }); + + it('returns null value', function (done) { + + expect(Hoek.cloneWithShallow(null)).to.equal(null); + done(); + }); + + it('returns undefined value', function (done) { + + expect(Hoek.cloneWithShallow(undefined)).to.equal(undefined); + done(); + }); + + it('deep clones except for listed keys (including missing keys)', function (done) { + + var source = { + a: { + b: 5 + }, + c: { + d: 6 + } + }; + + var copy = Hoek.cloneWithShallow(source, ['c', 'v']); + expect(copy).to.deep.equal(source); + expect(copy).to.not.equal(source); + expect(copy.a).to.not.equal(source.a); + expect(copy.b).to.equal(source.b); + done(); + }); +}); + +describe('applyToDefaultsWithShallow()', function () { + + it('shallow copies the listed keys from options without merging', function (done) { + + var defaults = { + a: { + b: 5, + e: 3 + }, + c: { + d: 7, + g: 1 + } + }; + + var options = { + a: { + b: 4 + }, + c: { + d: 6, + f: 7 + } + }; + + var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['a']); + expect(merged).to.deep.equal({ a: { b: 4 }, c: { d: 6, g: 1, f: 7 } }); + expect(merged.a).to.equal(options.a); + expect(merged.a).to.not.equal(defaults.a); + expect(merged.c).to.not.equal(options.c); + expect(merged.c).to.not.equal(defaults.c); + done(); + }); + + it('shallow copies the nested keys (override)', function (done) { + + var defaults = { + a: { + b: 5 + }, + c: { + d: 7, + g: 1 + } + }; + + var options = { + a: { + b: 4 + }, + c: { + d: 6, + g: { + h: 8 + } + } + }; + + var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['c.g']); + expect(merged).to.deep.equal({ a: { b: 4 }, c: { d: 6, g: { h: 8 } } }); + expect(merged.c.g).to.equal(options.c.g); + done(); + }); + + it('shallow copies the nested keys (missing)', function (done) { + + var defaults = { + a: { + b: 5 + } + }; + + var options = { + a: { + b: 4 + }, + c: { + g: { + h: 8 + } + } + }; + + var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['c.g']); + expect(merged).to.deep.equal({ a: { b: 4 }, c: { g: { h: 8 } } }); + expect(merged.c.g).to.equal(options.c.g); + done(); + }); + + it('shallow copies the nested keys (override)', function (done) { + + var defaults = { + a: { + b: 5 + }, + c: { + g: { + d: 7 + } + } + }; + + var options = { + a: { + b: 4 + }, + c: { + g: { + h: 8 + } + } + }; + + var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['c.g']); + expect(merged).to.deep.equal({ a: { b: 4 }, c: { g: { h: 8 } } }); + expect(merged.c.g).to.equal(options.c.g); + done(); + }); + + it('shallow copies the nested keys (deeper)', function (done) { + + var defaults = { + a: { + b: 5 + } + }; + + var options = { + a: { + b: 4 + }, + c: { + g: { + r: { + h: 8 + } + } + } + }; + + var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['c.g.r']); + expect(merged).to.deep.equal({ a: { b: 4 }, c: { g: { r: { h: 8 } } } }); + expect(merged.c.g.r).to.equal(options.c.g.r); + done(); + }); + + it('shallow copies the nested keys (not present)', function (done) { + + var defaults = { + a: { + b: 5 + } + }; + + var options = { + a: { + b: 4 + }, + c: { + g: { + r: { + h: 8 + } + } + } + }; + + var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['x.y']); + expect(merged).to.deep.equal({ a: { b: 4 }, c: { g: { r: { h: 8 } } } }); + done(); + }); + + it('shallow copies the listed keys in the defaults', function (done) { + + var defaults = { + a: { + b: 1 + } + }; + + var merged = Hoek.applyToDefaultsWithShallow(defaults, {}, ['a']); + expect(merged.a).to.equal(defaults.a); + done(); + }); + + it('shallow copies the listed keys in the defaults (true)', function (done) { + + var defaults = { + a: { + b: 1 + } + }; + + var merged = Hoek.applyToDefaultsWithShallow(defaults, true, ['a']); + expect(merged.a).to.equal(defaults.a); + done(); + }); + + it('returns null on false', function (done) { + + var defaults = { + a: { + b: 1 + } + }; + + var merged = Hoek.applyToDefaultsWithShallow(defaults, false, ['a']); + expect(merged).to.equal(null); + done(); + }); + + it('throws on missing defaults', function (done) { + + expect(function () { + + Hoek.applyToDefaultsWithShallow(null, {}, ['a']); + }).to.throw('Invalid defaults value: must be an object'); + done(); + }); + + it('throws on invalid defaults', function (done) { + + expect(function () { + + Hoek.applyToDefaultsWithShallow('abc', {}, ['a']); + }).to.throw('Invalid defaults value: must be an object'); + done(); + }); + + it('throws on invalid options', function (done) { + + expect(function () { + + Hoek.applyToDefaultsWithShallow({}, 'abc', ['a']); + }).to.throw('Invalid options value: must be true, falsy or an object'); + done(); + }); + + it('throws on missing keys', function (done) { + + expect(function () { + + Hoek.applyToDefaultsWithShallow({}, true); + }).to.throw('Invalid keys'); + done(); + }); + + it('throws on invalid keys', function (done) { + + expect(function () { + + Hoek.applyToDefaultsWithShallow({}, true, 'a'); + }).to.throw('Invalid keys'); + done(); + }); +}); + +describe('deepEqual()', function () { + + it('compares simple values', function (done) { + + expect(Hoek.deepEqual('x', 'x')).to.be.true(); + expect(Hoek.deepEqual('x', 'y')).to.be.false(); + expect(Hoek.deepEqual('x1', 'x')).to.be.false(); + expect(Hoek.deepEqual(-0, +0)).to.be.false(); + expect(Hoek.deepEqual(-0, -0)).to.be.true(); + expect(Hoek.deepEqual(+0, +0)).to.be.true(); + expect(Hoek.deepEqual(+0, -0)).to.be.false(); + expect(Hoek.deepEqual(1, 1)).to.be.true(); + expect(Hoek.deepEqual(0, 0)).to.be.true(); + expect(Hoek.deepEqual(-1, 1)).to.be.false(); + expect(Hoek.deepEqual(NaN, 0)).to.be.false(); + expect(Hoek.deepEqual(NaN, NaN)).to.be.true(); + done(); + }); + + it('compares different types', function (done) { + + expect(Hoek.deepEqual([], 5)).to.be.false(); + expect(Hoek.deepEqual(5, [])).to.be.false(); + expect(Hoek.deepEqual({}, null)).to.be.false(); + expect(Hoek.deepEqual(null, {})).to.be.false(); + expect(Hoek.deepEqual('abc', {})).to.be.false(); + expect(Hoek.deepEqual({}, 'abc')).to.be.false(); + done(); + }); + + it('compares empty structures', function (done) { + + expect(Hoek.deepEqual([], [])).to.be.true(); + expect(Hoek.deepEqual({}, {})).to.be.true(); + expect(Hoek.deepEqual([], {})).to.be.false(); + done(); + }); + + it('compares empty arguments object', function (done) { + + var compare = function () { + + expect(Hoek.deepEqual([], arguments)).to.be.false(); + }; + + compare(); + done(); + }); + + it('compares empty arguments objects', function (done) { + + var compare = function () { + + var arg1 = arguments; + + var inner = function () { + + expect(Hoek.deepEqual(arg1, arguments)).to.be.false(); // callee is not the same + }; + + inner(); + }; + + compare(); + done(); + }); + + it('compares dates', function (done) { + + expect(Hoek.deepEqual(new Date(2015, 1, 1), new Date(2015, 1, 1))).to.be.true(); + expect(Hoek.deepEqual(new Date(100), new Date(101))).to.be.false(); + expect(Hoek.deepEqual(new Date(), {})).to.be.false(); + done(); + }); + + it('compares regular expressions', function (done) { + + expect(Hoek.deepEqual(/\s/, new RegExp('\\\s'))).to.be.true(); + expect(Hoek.deepEqual(/\s/g, /\s/g)).to.be.true(); + expect(Hoek.deepEqual(/a/, {})).to.be.false(); + expect(Hoek.deepEqual(/\s/g, /\s/i)).to.be.false(); + expect(Hoek.deepEqual(/a/g, /b/g)).to.be.false(); + done(); + }); + + it('compares arrays', function (done) { + + expect(Hoek.deepEqual([[1]], [[1]])).to.be.true(); + expect(Hoek.deepEqual([1, 2, 3], [1, 2, 3])).to.be.true(); + expect(Hoek.deepEqual([1, 2, 3], [1, 3, 2])).to.be.false(); + expect(Hoek.deepEqual([1, 2, 3], [1, 2])).to.be.false(); + expect(Hoek.deepEqual([1], [1])).to.be.true(); + done(); + }); + + it('compares buffers', function (done) { + + expect(Hoek.deepEqual(new Buffer([1, 2, 3]), new Buffer([1, 2, 3]))).to.be.true(); + expect(Hoek.deepEqual(new Buffer([1, 2, 3]), new Buffer([1, 3, 2]))).to.be.false(); + expect(Hoek.deepEqual(new Buffer([1, 2, 3]), new Buffer([1, 2]))).to.be.false(); + expect(Hoek.deepEqual(new Buffer([1, 2, 3]), {})).to.be.false(); + expect(Hoek.deepEqual(new Buffer([1, 2, 3]), [1, 2, 3])).to.be.false(); + done(); + }); + + it('compares objects', function (done) { + + expect(Hoek.deepEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 })).to.be.true(); + expect(Hoek.deepEqual({ foo: 'bar' }, { foo: 'baz' })).to.be.false(); + expect(Hoek.deepEqual({ foo: { bar: 'foo' } }, { foo: { bar: 'baz' } })).to.be.false(); + done(); + }); + + it('handles circular dependency', function (done) { + + var a = {}; + a.x = a; + + var b = Hoek.clone(a); + expect(Hoek.deepEqual(a, b)).to.be.true(); + done(); + }); + + it('compares an object with property getter without executing it', function (done) { + + var obj = {}; + var value = 1; + var execCount = 0; + + Object.defineProperty(obj, 'test', { + enumerable: true, + configurable: true, + get: function () { + + ++execCount; + return value; + } + }); + + var copy = Hoek.clone(obj); + expect(Hoek.deepEqual(obj, copy)).to.be.true(); + expect(execCount).to.equal(0); + expect(copy.test).to.equal(1); + expect(execCount).to.equal(1); + done(); + }); + + it('compares objects with property getters', function (done) { + + var obj = {}; + Object.defineProperty(obj, 'test', { + enumerable: true, + configurable: true, + get: function () { + + return 1; + } + }); + + var ref = {}; + Object.defineProperty(ref, 'test', { + enumerable: true, + configurable: true, + get: function () { + + return 2; + } + }); + + expect(Hoek.deepEqual(obj, ref)).to.be.false(); + done(); + }); + + it('compares object prototypes', function (done) { + + var Obj = function () { + + this.a = 5; + }; + + Obj.prototype.b = function () { + + return this.a; + }; + + var Ref = function () { + + this.a = 5; + }; + + Ref.prototype.b = function () { + + return this.a; + }; + + expect(Hoek.deepEqual(new Obj(), new Ref())).to.be.false(); + expect(Hoek.deepEqual(new Obj(), new Obj())).to.be.true(); + expect(Hoek.deepEqual(new Ref(), new Ref())).to.be.true(); + done(); + }); + + it('compares plain objects', function (done) { + + var a = Object.create(null); + var b = Object.create(null); + + a.b = 'c'; + b.b = 'c'; + + expect(Hoek.deepEqual(a, b)).to.be.true(); + expect(Hoek.deepEqual(a, { b: 'c' })).to.be.false(); + done(); + }); + + it('compares an object with an empty object', function (done) { + + var a = { a: 1, b: 2 }; + + expect(Hoek.deepEqual({}, a)).to.be.false(); + expect(Hoek.deepEqual(a, {})).to.be.false(); + done(); + }); + + it('compares an object ignoring the prototype', function (done) { + + var a = Object.create(null); + var b = {}; + + expect(Hoek.deepEqual(a, b, { prototype: false })).to.be.true(); + done(); + }); + + it('compares an object ignoring the prototype recursively', function (done) { + + var a = [Object.create(null)]; + var b = [{}]; + + expect(Hoek.deepEqual(a, b, { prototype: false })).to.be.true(); + done(); + }); +}); + +describe('unique()', function () { + + it('ensures uniqueness within array of objects based on subkey', function (done) { + + var a = Hoek.unique(dupsArray, 'x'); + expect(a).to.deep.equal(reducedDupsArray); + done(); + }); + + it('removes duplicated without key', function (done) { + + expect(Hoek.unique([1, 2, 3, 4, 2, 1, 5])).to.deep.equal([1, 2, 3, 4, 5]); + done(); + }); +}); + +describe('mapToObject()', function () { + + it('returns null on null array', function (done) { + + var a = Hoek.mapToObject(null); + expect(a).to.equal(null); + done(); + }); + + it('converts basic array to existential object', function (done) { + + var keys = [1, 2, 3, 4]; + var a = Hoek.mapToObject(keys); + for (var i in keys) { + expect(a[keys[i]]).to.equal(true); + } + done(); + }); + + it('converts array of objects to existential object', function (done) { + + var keys = [{ x: 1 }, { x: 2 }, { x: 3 }, { y: 4 }]; + var subkey = 'x'; + var a = Hoek.mapToObject(keys, subkey); + expect(a).to.deep.equal({ 1: true, 2: true, 3: true }); + done(); + }); +}); + +describe('intersect()', function () { + + it('returns the common objects of two arrays', function (done) { + + var array1 = [1, 2, 3, 4, 4, 5, 5]; + var array2 = [5, 4, 5, 6, 7]; + var common = Hoek.intersect(array1, array2); + expect(common.length).to.equal(2); + done(); + }); + + it('returns just the first common object of two arrays', function (done) { + + var array1 = [1, 2, 3, 4, 4, 5, 5]; + var array2 = [5, 4, 5, 6, 7]; + var common = Hoek.intersect(array1, array2, true); + expect(common).to.equal(5); + done(); + }); + + it('returns null when no common and returning just the first common object of two arrays', function (done) { + + var array1 = [1, 2, 3, 4, 4, 5, 5]; + var array2 = [6, 7]; + var common = Hoek.intersect(array1, array2, true); + expect(common).to.equal(null); + done(); + }); + + it('returns an empty array if either input is null', function (done) { + + expect(Hoek.intersect([1], null).length).to.equal(0); + expect(Hoek.intersect(null, [1]).length).to.equal(0); + done(); + }); + + it('returns the common objects of object and array', function (done) { + + var array1 = [1, 2, 3, 4, 4, 5, 5]; + var array2 = [5, 4, 5, 6, 7]; + var common = Hoek.intersect(Hoek.mapToObject(array1), array2); + expect(common.length).to.equal(2); + done(); + }); +}); + +describe('contain()', function () { + + it('tests strings', function (done) { + + expect(Hoek.contain('abc', 'ab')).to.be.true(); + expect(Hoek.contain('abc', 'abc', { only: true })).to.be.true(); + expect(Hoek.contain('aaa', 'a', { only: true })).to.be.true(); + expect(Hoek.contain('abc', 'b', { once: true })).to.be.true(); + expect(Hoek.contain('abc', ['a', 'c'])).to.be.true(); + expect(Hoek.contain('abc', ['a', 'd'], { part: true })).to.be.true(); + + expect(Hoek.contain('abc', 'ac')).to.be.false(); + expect(Hoek.contain('abcd', 'abc', { only: true })).to.be.false(); + expect(Hoek.contain('aab', 'a', { only: true })).to.be.false(); + expect(Hoek.contain('abb', 'b', { once: true })).to.be.false(); + expect(Hoek.contain('abc', ['a', 'd'])).to.be.false(); + expect(Hoek.contain('abc', ['ab', 'bc'])).to.be.false(); // Overlapping values not supported + done(); + }); + + it('tests arrays', function (done) { + + expect(Hoek.contain([1, 2, 3], 1)).to.be.true(); + expect(Hoek.contain([{ a: 1 }], { a: 1 }, { deep: true })).to.be.true(); + expect(Hoek.contain([1, 2, 3], [1, 2])).to.be.true(); + expect(Hoek.contain([{ a: 1 }], [{ a: 1 }], { deep: true })).to.be.true(); + expect(Hoek.contain([1, 1, 2], [1, 2], { only: true })).to.be.true(); + expect(Hoek.contain([1, 2], [1, 2], { once: true })).to.be.true(); + expect(Hoek.contain([1, 2, 3], [1, 4], { part: true })).to.be.true(); + expect(Hoek.contain([[1], [2]], [[1]], { deep: true })).to.be.true(); + + expect(Hoek.contain([1, 2, 3], 4)).to.be.false(); + expect(Hoek.contain([{ a: 1 }], { a: 2 }, { deep: true })).to.be.false(); + expect(Hoek.contain([{ a: 1 }], { a: 1 })).to.be.false(); + expect(Hoek.contain([1, 2, 3], [4, 5])).to.be.false(); + expect(Hoek.contain([[3], [2]], [[1]])).to.be.false(); + expect(Hoek.contain([[1], [2]], [[1]])).to.be.false(); + expect(Hoek.contain([{ a: 1 }], [{ a: 2 }], { deep: true })).to.be.false(); + expect(Hoek.contain([1, 3, 2], [1, 2], { only: true })).to.be.false(); + expect(Hoek.contain([1, 2, 2], [1, 2], { once: true })).to.be.false(); + expect(Hoek.contain([0, 2, 3], [1, 4], { part: true })).to.be.false(); + done(); + }); + + it('tests objects', function (done) { + + expect(Hoek.contain({ a: 1, b: 2, c: 3 }, 'a')).to.be.true(); + expect(Hoek.contain({ a: 1, b: 2, c: 3 }, ['a', 'c'])).to.be.true(); + expect(Hoek.contain({ a: 1, b: 2, c: 3 }, ['a', 'b', 'c'], { only: true })).to.be.true(); + expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1 })).to.be.true(); + expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, c: 3 })).to.be.true(); + expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, d: 4 }, { part: true })).to.be.true(); + expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 }, { only: true })).to.be.true(); + expect(Hoek.contain({ a: [1], b: [2], c: [3] }, { a: [1], c: [3] }, { deep: true })).to.be.true(); + expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true })).to.be.true(); + expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true, part: true })).to.be.true(); + expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true, part: false })).to.be.false(); + expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true, only: true })).to.be.false(); + expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true, only: false })).to.be.true(); + + expect(Hoek.contain({ a: 1, b: 2, c: 3 }, 'd')).to.be.false(); + expect(Hoek.contain({ a: 1, b: 2, c: 3 }, ['a', 'd'])).to.be.false(); + expect(Hoek.contain({ a: 1, b: 2, c: 3, d: 4 }, ['a', 'b', 'c'], { only: true })).to.be.false(); + expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 2 })).to.be.false(); + expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 2, b: 2 }, { part: true })).to.be.false(); // part does not ignore bad value + expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, d: 3 })).to.be.false(); + expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, d: 4 })).to.be.false(); + expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, b: 2 }, { only: true })).to.be.false(); + expect(Hoek.contain({ a: [1], b: [2], c: [3] }, { a: [1], c: [3] })).to.be.false(); + expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } })).to.be.false(); + expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true })).to.be.true(); + expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true, only: true })).to.be.false(); + expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true, only: false })).to.be.true(); + expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true, part: true })).to.be.true(); + expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true, part: false })).to.be.false(); + + // Getter check + var Foo = function (bar) { + + this.bar = bar; + }; + + Object.defineProperty(Foo.prototype, 'baz', { + enumerable: true, + get: function () { + + return this.bar; + } + }); + + expect(Hoek.contain({ a: new Foo('b') }, { a: new Foo('b') }, { deep: true })).to.be.true(); + expect(Hoek.contain({ a: new Foo('b') }, { a: new Foo('b') }, { deep: true, part: true })).to.be.true(); + expect(Hoek.contain({ a: new Foo('b') }, { a: { baz: 'b' } }, { deep: true })).to.be.true(); + expect(Hoek.contain({ a: new Foo('b') }, { a: { baz: 'b' } }, { deep: true, only: true })).to.be.false(); + expect(Hoek.contain({ a: new Foo('b') }, { a: { baz: 'b' } }, { deep: true, part: false })).to.be.false(); + expect(Hoek.contain({ a: new Foo('b') }, { a: { baz: 'b' } }, { deep: true, part: true })).to.be.true(); + + done(); + }); +}); + +describe('flatten()', function () { + + it('returns a flat array', function (done) { + + var result = Hoek.flatten([1, 2, [3, 4, [5, 6], [7], 8], [9], [10, [11, 12]], 13]); + expect(result.length).to.equal(13); + expect(result).to.deep.equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]); + done(); + }); +}); + +describe('reach()', function () { + + var obj = { + a: { + b: { + c: { + d: 1, + e: 2 + }, + f: 'hello' + }, + g: { + h: 3 + } + }, + i: function () { }, + j: null, + k: [4, 8, 9, 1] + }; + + obj.i.x = 5; + + it('returns object itself', function (done) { + + expect(Hoek.reach(obj, null)).to.equal(obj); + expect(Hoek.reach(obj, false)).to.equal(obj); + expect(Hoek.reach(obj)).to.equal(obj); + done(); + }); + + it('returns first value of array', function (done) { + + expect(Hoek.reach(obj, 'k.0')).to.equal(4); + done(); + }); + + it('returns last value of array using negative index', function (done) { + + expect(Hoek.reach(obj, 'k.-2')).to.equal(9); + done(); + }); + + it('returns a valid member', function (done) { + + expect(Hoek.reach(obj, 'a.b.c.d')).to.equal(1); + done(); + }); + + it('returns a valid member with separator override', function (done) { + + expect(Hoek.reach(obj, 'a/b/c/d', '/')).to.equal(1); + done(); + }); + + it('returns undefined on null object', function (done) { + + expect(Hoek.reach(null, 'a.b.c.d')).to.equal(undefined); + done(); + }); + + it('returns undefined on missing object member', function (done) { + + expect(Hoek.reach(obj, 'a.b.c.d.x')).to.equal(undefined); + done(); + }); + + it('returns undefined on missing function member', function (done) { + + expect(Hoek.reach(obj, 'i.y', { functions: true })).to.equal(undefined); + done(); + }); + + it('throws on missing member in strict mode', function (done) { + + expect(function () { + + Hoek.reach(obj, 'a.b.c.o.x', { strict: true }); + }).to.throw('Missing segment o in reach path a.b.c.o.x'); + + done(); + }); + + it('returns undefined on invalid member', function (done) { + + expect(Hoek.reach(obj, 'a.b.c.d-.x')).to.equal(undefined); + done(); + }); + + it('returns function member', function (done) { + + expect(typeof Hoek.reach(obj, 'i')).to.equal('function'); + done(); + }); + + it('returns function property', function (done) { + + expect(Hoek.reach(obj, 'i.x')).to.equal(5); + done(); + }); + + it('returns null', function (done) { + + expect(Hoek.reach(obj, 'j')).to.equal(null); + done(); + }); + + it('throws on function property when functions not allowed', function (done) { + + expect(function () { + + Hoek.reach(obj, 'i.x', { functions: false }); + }).to.throw('Invalid segment x in reach path i.x'); + + done(); + }); + + it('will return a default value if property is not found', function (done) { + + expect(Hoek.reach(obj, 'a.b.q', { default: 'defaultValue' })).to.equal('defaultValue'); + done(); + }); + + it('will return a default value if path is not found', function (done) { + + expect(Hoek.reach(obj, 'q', { default: 'defaultValue' })).to.equal('defaultValue'); + done(); + }); + + it('allows a falsey value to be used as the default value', function (done) { + + expect(Hoek.reach(obj, 'q', { default: '' })).to.equal(''); + done(); + }); +}); + +describe('reachTemplate()', function () { + + it('applies object to template', function (done) { + + var obj = { + a: { + b: { + c: { + d: 1 + } + } + }, + j: null, + k: [4, 8, 9, 1] + }; + + var template = '{k.0}:{k.-2}:{a.b.c.d}:{x.y}:{j}'; + + expect(Hoek.reachTemplate(obj, template)).to.equal('4:9:1::'); + done(); + }); + + it('applies object to template (options)', function (done) { + + var obj = { + a: { + b: { + c: { + d: 1 + } + } + }, + j: null, + k: [4, 8, 9, 1] + }; + + var template = '{k/0}:{k/-2}:{a/b/c/d}:{x/y}:{j}'; + + expect(Hoek.reachTemplate(obj, template, '/')).to.equal('4:9:1::'); + done(); + }); +}); + +describe('callStack()', function () { + + it('returns the full call stack', function (done) { + + var stack = Hoek.callStack(); + expect(stack[0][0]).to.contain('index.js'); + expect(stack[0][2]).to.equal(26); + done(); + }); +}); + +describe('displayStack ()', function () { + + it('returns the full call stack for display', function (done) { + + var stack = Hoek.displayStack(); + expect(stack[0]).to.contain(Path.normalize('/test/index.js') + ':'); + done(); + }); + + it('includes constructor functions correctly', function (done) { + + var Something = function (next) { + + next(); + }; + + var something = new Something(function () { + + var stack = Hoek.displayStack(); + expect(stack[1]).to.contain('new Something'); + done(); + }); + }); +}); + +describe('abort()', function () { + + it('exits process when not in test mode', function (done) { + + var env = process.env.NODE_ENV; + var write = process.stdout.write; + var exit = process.exit; + + process.env.NODE_ENV = 'nottatest'; + process.stdout.write = function () { }; + process.exit = function (state) { + + process.exit = exit; + process.env.NODE_ENV = env; + process.stdout.write = write; + + expect(state).to.equal(1); + done(); + }; + + Hoek.abort('Boom'); + }); + + it('throws when not in test mode and abortThrow is true', function (done) { + + var env = process.env.NODE_ENV; + process.env.NODE_ENV = 'nottatest'; + Hoek.abortThrow = true; + + var fn = function () { + + Hoek.abort('my error message'); + }; + + expect(fn).to.throw('my error message'); + Hoek.abortThrow = false; + process.env.NODE_ENV = env; + + done(); + }); + + it('respects hideStack argument', function (done) { + + var env = process.env.NODE_ENV; + var write = process.stdout.write; + var exit = process.exit; + var output = ''; + + process.exit = function () { }; + process.env.NODE_ENV = ''; + process.stdout.write = function (message) { + + output = message; + }; + + Hoek.abort('my error message', true); + + process.env.NODE_ENV = env; + process.stdout.write = write; + process.exit = exit; + + expect(output).to.equal('ABORT: my error message\n\t\n'); + + done(); + }); + + it('throws in test mode', function (done) { + + var env = process.env.NODE_ENV; + process.env.NODE_ENV = 'test'; + + expect(function () { + + Hoek.abort('my error message', true); + }).to.throw('my error message'); + + process.env.NODE_ENV = env; + done(); + }); + + it('throws in test mode with default message', function (done) { + + var env = process.env.NODE_ENV; + process.env.NODE_ENV = 'test'; + + expect(function () { + + Hoek.abort('', true); + }).to.throw('Unknown error'); + + process.env.NODE_ENV = env; + done(); + }); + + it('defaults to showing stack', function (done) { + + var env = process.env.NODE_ENV; + var write = process.stdout.write; + var exit = process.exit; + var output = ''; + + process.exit = function () { }; + process.env.NODE_ENV = ''; + process.stdout.write = function (message) { + + output = message; + }; + + Hoek.abort('my error message'); + + process.env.NODE_ENV = env; + process.stdout.write = write; + process.exit = exit; + + expect(output).to.contain('index.js'); + + done(); + }); +}); + +describe('assert()', function () { + + it('throws an Error when using assert in a test', function (done) { + + var fn = function () { + + Hoek.assert(false, 'my error message'); + }; + + expect(fn).to.throw('my error message'); + done(); + }); + + it('throws an Error when using assert in a test with no message', function (done) { + + var fn = function () { + + Hoek.assert(false); + }; + + expect(fn).to.throw('Unknown error'); + done(); + }); + + it('throws an Error when using assert in a test with multipart message', function (done) { + + var fn = function () { + + Hoek.assert(false, 'This', 'is', 'my message'); + }; + + expect(fn).to.throw('This is my message'); + done(); + }); + + it('throws an Error when using assert in a test with multipart message (empty)', function (done) { + + var fn = function () { + + Hoek.assert(false, 'This', 'is', '', 'my message'); + }; + + expect(fn).to.throw('This is my message'); + done(); + }); + + it('throws an Error when using assert in a test with object message', function (done) { + + var fn = function () { + + Hoek.assert(false, 'This', 'is', { spinal: 'tap' }); + }; + + expect(fn).to.throw('This is {"spinal":"tap"}'); + done(); + }); + + it('throws an Error when using assert in a test with multipart string and error messages', function (done) { + + var fn = function () { + + Hoek.assert(false, 'This', 'is', new Error('spinal'), new Error('tap')); + }; + + expect(fn).to.throw('This is spinal tap'); + done(); + }); + + it('throws an Error when using assert in a test with error object message', function (done) { + + var fn = function () { + + Hoek.assert(false, new Error('This is spinal tap')); + }; + + expect(fn).to.throw('This is spinal tap'); + done(); + }); + + it('throws the same Error that is passed to it if there is only one error passed', function (done) { + + var error = new Error('ruh roh'); + var error2 = new Error('ruh roh'); + + var fn = function () { + + Hoek.assert(false, error); + }; + + try { + fn(); + } catch (err) { + expect(error).to.equal(error); // should be the same reference + expect(error).to.not.equal(error2); // error with the same message should not match + } + + done(); + }); +}); + +describe('Timer', function () { + + it('returns time elapsed', function (done) { + + var timer = new Hoek.Timer(); + setTimeout(function () { + + expect(timer.elapsed()).to.be.above(9); + done(); + }, 12); + }); +}); + +describe('Bench', function () { + + it('returns time elapsed', function (done) { + + var timer = new Hoek.Bench(); + setTimeout(function () { + + expect(timer.elapsed()).to.be.above(9); + done(); + }, 12); + }); +}); + +describe('escapeRegex()', function () { + + it('escapes all special regular expression characters', function (done) { + + var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,'); + expect(a).to.equal('4\\^f\\$s\\.4\\*5\\+\\-_\\?%\\=#\\!\\:@\\|~\\\\\\/`"\\(>\\)\\[<\\]d\\{\\}s\\,'); + done(); + }); +}); + +describe('Base64Url', function () { + + var base64str = 'AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w'; + var str = unescape('%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29*+%2C-./0123456789%3A%3B%3C%3D%3E%3F@ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF'); + + describe('base64urlEncode()', function () { + + it('should base64 URL-safe a string', function (done) { + + expect(Hoek.base64urlEncode(str)).to.equal(base64str); + done(); + }); + + it('encodes a buffer', function (done) { + + expect(Hoek.base64urlEncode(new Buffer(str, 'binary'))).to.equal(base64str); + done(); + }); + + it('should base64 URL-safe a hex string', function (done) { + + var buffer = new Buffer(str, 'binary'); + expect(Hoek.base64urlEncode(buffer.toString('hex'), 'hex')).to.equal(base64str); + done(); + }); + + it('works on larger input strings', function (done) { + + var input = Fs.readFileSync(Path.join(__dirname, 'index.js')).toString(); + var encoded = Hoek.base64urlEncode(input); + + expect(encoded).to.not.contain('+'); + expect(encoded).to.not.contain('/'); + + var decoded = Hoek.base64urlDecode(encoded); + + expect(decoded).to.equal(input); + done(); + }); + }); + + describe('base64urlDecode()', function () { + + it('should un-base64 URL-safe a string', function (done) { + + expect(Hoek.base64urlDecode(base64str)).to.equal(str); + done(); + }); + + it('should un-base64 URL-safe a string into hex', function (done) { + + expect(Hoek.base64urlDecode(base64str, 'hex')).to.equal(new Buffer(str, 'binary').toString('hex')); + done(); + }); + + it('should un-base64 URL-safe a string and return a buffer', function (done) { + + var buf = Hoek.base64urlDecode(base64str, 'buffer'); + expect(buf instanceof Buffer).to.equal(true); + expect(buf.toString('binary')).to.equal(str); + done(); + }); + + it('returns error on undefined input', function (done) { + + expect(Hoek.base64urlDecode().message).to.exist(); + done(); + }); + + it('returns error on invalid input', function (done) { + + expect(Hoek.base64urlDecode('*').message).to.exist(); + done(); + }); + }); +}); + +describe('escapeHeaderAttribute()', function () { + + it('should not alter ascii values', function (done) { + + var a = Hoek.escapeHeaderAttribute('My Value'); + expect(a).to.equal('My Value'); + done(); + }); + + it('escapes all special HTTP header attribute characters', function (done) { + + var a = Hoek.escapeHeaderAttribute('I said go!!!#"' + String.fromCharCode(92)); + expect(a).to.equal('I said go!!!#\\"\\\\'); + done(); + }); + + it('throws on large unicode characters', function (done) { + + var fn = function () { + + Hoek.escapeHeaderAttribute('this is a test' + String.fromCharCode(500) + String.fromCharCode(300)); + }; + + expect(fn).to.throw(Error); + done(); + }); + + it('throws on CRLF to prevent response splitting', function (done) { + + var fn = function () { + + Hoek.escapeHeaderAttribute('this is a test\r\n'); + }; + + expect(fn).to.throw(Error); + done(); + }); +}); + +describe('escapeHtml()', function () { + + it('escapes all special HTML characters', function (done) { + + var a = Hoek.escapeHtml('&<>"\'`'); + expect(a).to.equal('&<>"'`'); + done(); + }); + + it('returns empty string on falsy input', function (done) { + + var a = Hoek.escapeHtml(''); + expect(a).to.equal(''); + done(); + }); + + it('returns unchanged string on no reserved input', function (done) { + + var a = Hoek.escapeHtml('abc'); + expect(a).to.equal('abc'); + done(); + }); +}); + +describe('nextTick()', function () { + + it('calls the provided callback on nextTick', function (done) { + + var a = 0; + + var inc = function (step, next) { + + a += step; + next(); + }; + + var ticked = Hoek.nextTick(inc); + + ticked(5, function () { + + expect(a).to.equal(6); + done(); + }); + + expect(a).to.equal(0); + inc(1, function () { + + expect(a).to.equal(1); + }); + }); +}); + +describe('once()', function () { + + it('allows function to only execute once', function (done) { + + var gen = 0; + var add = function (x) { + + gen += x; + }; + + add(5); + expect(gen).to.equal(5); + add = Hoek.once(add); + add(5); + expect(gen).to.equal(10); + add(5); + expect(gen).to.equal(10); + done(); + }); + + it('double once wraps one time', function (done) { + + var method = function () { }; + method = Hoek.once(method); + method.x = 1; + method = Hoek.once(method); + expect(method.x).to.equal(1); + done(); + }); +}); + +describe('isAbsoltePath()', function () { + + it('identifies if path is absolute on Unix without node support', { parallel: false }, function (done) { + + var orig = Path.isAbsolute; + Path.isAbsolute = undefined; + + expect(Hoek.isAbsolutePath('')).to.equal(false); + expect(Hoek.isAbsolutePath('a')).to.equal(false); + expect(Hoek.isAbsolutePath('./a')).to.equal(false); + expect(Hoek.isAbsolutePath('/a')).to.equal(true); + expect(Hoek.isAbsolutePath('/')).to.equal(true); + + Path.isAbsolute = orig; + + done(); + }); + + it('identifies if path is absolute with fake node support', { parallel: false }, function (done) { + + var orig = Path.isAbsolute; + Path.isAbsolute = function (path) { + + return path[0] === '/'; + }; + + expect(Hoek.isAbsolutePath('', 'linux')).to.equal(false); + expect(Hoek.isAbsolutePath('a', 'linux')).to.equal(false); + expect(Hoek.isAbsolutePath('./a', 'linux')).to.equal(false); + expect(Hoek.isAbsolutePath('/a', 'linux')).to.equal(true); + expect(Hoek.isAbsolutePath('/', 'linux')).to.equal(true); + + Path.isAbsolute = orig; + + done(); + }); + + it('identifies if path is absolute on Windows without node support', { parallel: false }, function (done) { + + var orig = Path.isAbsolute; + Path.isAbsolute = undefined; + + expect(Hoek.isAbsolutePath('//server/file', 'win32')).to.equal(true); + expect(Hoek.isAbsolutePath('//server/file', 'win32')).to.equal(true); + expect(Hoek.isAbsolutePath('\\\\server\\file', 'win32')).to.equal(true); + expect(Hoek.isAbsolutePath('C:/Users/', 'win32')).to.equal(true); + expect(Hoek.isAbsolutePath('C:\\Users\\', 'win32')).to.equal(true); + expect(Hoek.isAbsolutePath('C:cwd/another', 'win32')).to.equal(false); + expect(Hoek.isAbsolutePath('C:cwd\\another', 'win32')).to.equal(false); + expect(Hoek.isAbsolutePath('directory/directory', 'win32')).to.equal(false); + expect(Hoek.isAbsolutePath('directory\\directory', 'win32')).to.equal(false); + + Path.isAbsolute = orig; + + done(); + }); +}); + +describe('isInteger()', function () { + + it('validates integers', function (done) { + + expect(Hoek.isInteger(0)).to.equal(true); + expect(Hoek.isInteger(1)).to.equal(true); + expect(Hoek.isInteger(1394035612500)).to.equal(true); + expect(Hoek.isInteger('0')).to.equal(false); + expect(Hoek.isInteger(1.0)).to.equal(true); + expect(Hoek.isInteger(1.1)).to.equal(false); + done(); + }); +}); + +describe('ignore()', function () { + + it('exists', function (done) { + + expect(Hoek.ignore).to.exist(); + expect(typeof Hoek.ignore).to.equal('function'); + done(); + }); +}); + +describe('inherits()', function () { + + it('exists', function (done) { + + expect(Hoek.inherits).to.exist(); + expect(typeof Hoek.inherits).to.equal('function'); + done(); + }); +}); + +describe('format()', function () { + + it('exists', function (done) { + + expect(Hoek.format).to.exist(); + expect(typeof Hoek.format).to.equal('function'); + done(); + }); + + it('is a reference to Util.format', function (done) { + + expect(Hoek.format('hello %s', 'world')).to.equal('hello world'); + done(); + }); +}); + +describe('transform()', function () { + + var source = { + address: { + one: '123 main street', + two: 'PO Box 1234' + }, + zip: { + code: 3321232, + province: null + }, + title: 'Warehouse', + state: 'CA' + }; + + var sourcesArray = [{ + address: { + one: '123 main street', + two: 'PO Box 1234' + }, + zip: { + code: 3321232, + province: null + }, + title: 'Warehouse', + state: 'CA' + }, { + address: { + one: '456 market street', + two: 'PO Box 5678' + }, + zip: { + code: 9876, + province: null + }, + title: 'Garage', + state: 'NY' + }]; + + it('transforms an object based on the input object', function (done) { + + var result = Hoek.transform(source, { + 'person.address.lineOne': 'address.one', + 'person.address.lineTwo': 'address.two', + 'title': 'title', + 'person.address.region': 'state', + 'person.address.zip': 'zip.code', + 'person.address.location': 'zip.province' + }); + + expect(result).to.deep.equal({ + person: { + address: { + lineOne: '123 main street', + lineTwo: 'PO Box 1234', + region: 'CA', + zip: 3321232, + location: null + } + }, + title: 'Warehouse' + }); + + done(); + }); + + it('transforms an array of objects based on the input object', function (done) { + + var result = Hoek.transform(sourcesArray, { + 'person.address.lineOne': 'address.one', + 'person.address.lineTwo': 'address.two', + 'title': 'title', + 'person.address.region': 'state', + 'person.address.zip': 'zip.code', + 'person.address.location': 'zip.province' + }); + + expect(result).to.deep.equal([ + { + person: { + address: { + lineOne: '123 main street', + lineTwo: 'PO Box 1234', + region: 'CA', + zip: 3321232, + location: null + } + }, + title: 'Warehouse' + }, + { + person: { + address: { + lineOne: '456 market street', + lineTwo: 'PO Box 5678', + region: 'NY', + zip: 9876, + location: null + } + }, + title: 'Garage' + } + ]); + + done(); + }); + + it('uses the reach options passed into it', function (done) { + + var schema = { + 'person.address.lineOne': 'address-one', + 'person.address.lineTwo': 'address-two', + 'title': 'title', + 'person.address.region': 'state', + 'person.prefix': 'person-title', + 'person.zip': 'zip-code' + }; + var options = { + separator: '-', + default: 'unknown' + }; + var result = Hoek.transform(source, schema, options); + + expect(result).to.deep.equal({ + person: { + address: { + lineOne: '123 main street', + lineTwo: 'PO Box 1234', + region: 'CA' + }, + prefix: 'unknown', + zip: 3321232 + }, + title: 'Warehouse' + }); + + done(); + }); + + it('works to create shallow objects', function (done) { + + var result = Hoek.transform(source, { + lineOne: 'address.one', + lineTwo: 'address.two', + title: 'title', + region: 'state', + province: 'zip.province' + }); + + expect(result).to.deep.equal({ + lineOne: '123 main street', + lineTwo: 'PO Box 1234', + title: 'Warehouse', + region: 'CA', + province: null + }); + + done(); + }); + + it('only allows strings in the map', function (done) { + + expect(function () { + + var result = Hoek.transform(source, { + lineOne: {} + }); + }).to.throw('All mappings must be "." delineated strings'); + + done(); + }); + + it('throws an error on invalid arguments', function (done) { + + expect(function () { + + var result = Hoek.transform(NaN, {}); + }).to.throw('Invalid source object: must be null, undefined, an object, or an array'); + + done(); + }); + + it('is safe to pass null', function (done) { + + var result = Hoek.transform(null, {}); + expect(result).to.deep.equal({}); + + done(); + }); + + it('is safe to pass undefined', function (done) { + + var result = Hoek.transform(undefined, {}); + expect(result).to.deep.equal({}); + + done(); + }); +}); + +describe('uniqueFilename()', function () { + + it('generates a random file path', function (done) { + + var result = Hoek.uniqueFilename('./test/modules'); + + expect(result).to.exist(); + expect(result).to.be.a.string(); + expect(result).to.contain('test/modules'); + done(); + }); + + it('is random enough to use in fast loops', function (done) { + + var results = []; + + for (var i = 0; i < 10; ++i) { + results[i] = Hoek.uniqueFilename('./test/modules'); + } + + var filter = results.filter(function (item, index, array) { + + return array.indexOf(item) === index; + }); + + expect(filter.length).to.equal(10); + expect(results.length).to.equal(10); + done(); + + }); + + it('combines the random elements with a supplied character', function (done) { + + var result = Hoek.uniqueFilename('./test', 'txt'); + + expect(result).to.contain('test/'); + expect(result).to.contain('.txt'); + + done(); + }); + + it('accepts extensions with a "." in it', function (done) { + + var result = Hoek.uniqueFilename('./test', '.mp3'); + + expect(result).to.contain('test/'); + expect(result).to.contain('.mp3'); + + done(); + }); +}); + +describe('stringify()', function (done) { + + it('converts object to string', function (done) { + + var obj = { a: 1 }; + expect(Hoek.stringify(obj)).to.equal('{"a":1}'); + done(); + }); + + it('returns error in result string', function (done) { + + var obj = { a: 1 }; + obj.b = obj; + expect(Hoek.stringify(obj)).to.equal('[Cannot display object: Converting circular structure to JSON]'); + done(); + }); +}); + +describe('shallow()', function (done) { + + it('shallow copies an object', function (done) { + + var obj = { + a: 5, + b: { + c: 6 + } + }; + + var shallow = Hoek.shallow(obj); + expect(shallow).to.not.equal(obj); + expect(shallow).to.deep.equal(obj); + expect(shallow.b).to.equal(obj.b); + done(); + }); +});
@@ -0,0 +1,1 @@
+exports.x = 1;
@@ -0,0 +1,1 @@
+exports.y = 2;
@@ -0,0 +1,1 @@
+exports.z = 3;
@@ -0,0 +1,3 @@
+/coverage.html +/coverage.lcov +/node_modules
@@ -0,0 +1,5 @@
+language: node_js +node_js: + - "0.10" + - "4.0" +sudo: false
@@ -0,0 +1,13 @@
+Copyright © 2008-2011, Dominic Sayers +Copyright © 2013-2014, GlobeSherpa +Copyright © 2014-2015, Eli Skeggs + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +- Neither the name of Dominic Sayers nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,4 @@
+test: + npm test + +.PHONY: test
@@ -0,0 +1,95 @@
+isemail +======= + +Node email address validation library + +[](https://travis-ci.org/hapijs/isemail) +[](https://coveralls.io/r/hapijs/isemail?branch=master) + +Lead Maintainer: [Eli Skeggs](https://github.com/skeggse) + +This first version of `isemail` is a port of the PHP `is_email` function by Dominic Sayers. + +Install +------- + +```sh +$ npm install isemail +``` + +Test +---- + +The tests were pulled from is_email's extensive [test suite][tests] on October 15, 2013. Many thanks to the contributors! Additional tests have been added to increase code coverage and verify edge-cases. + +Run any of the following. + +```sh +$ lab +$ npm test +$ make test +``` + +_remember to_ `npm install`! + +API +--- + +### isEmail(email, [options], [callback]) + +Determines whether the `email` is valid or not, for various definitions thereof. Optionally accepts an `options` object and a `callback` function. Options may include `errorLevel` and `checkDNS`. The `callback` function will always be called if specified, and the result of the operation supplied as the only parameter to the callback function. If `isEmail` is not asked to check for the existence of the domain (`checkDNS`), it will also synchronously return the result of the operation. + +Use `errorLevel` to specify the type of result for `isEmail`. Passing a `false` literal will result in a true or false boolean indicating whether the email address is sufficiently defined for use in sending an email. Passing a `true` literal will result in a more granular numeric status, with zero being a perfectly valid email address. Passing a number will return `0` if the numeric status is below the `errorLevel` and the numeric status otherwise. + +The `tldWhitelist` option can be either an object lookup table or an array of valid top-level domains. If the email address has a top-level domain that is not in the whitelist, the email will be marked as invalid. + +The `minDomainAtoms` option is an optional positive integer that specifies the minimum number of domain atoms that must be included for the email address to be considered valid. Be careful with the option, as some top-level domains, like `io`, directly support email addresses. To better handle fringe cases like the `io` TLD, use the `checkDNS` parameter, which will only allow email addresses for domains which have an MX record. + +#### Examples + +```js +$ node +> var isEmail = require('isemail'); +undefined +> var log = console.log.bind(console, 'result'); +undefined +> isEmail('test@iana.org'); +true +> isEmail('test@iana.org', log); +result true +true +> isEmail('test@iana.org', {checkDNS: true}); +undefined +> isEmail('test@iana.org', {checkDNS: true}, log); +undefined +result true +> isEmail('test@iana.org', {errorLevel: true}); +0 +> isEmail('test@iana.org', {errorLevel: true}, log); +result 0 +0 +> isEmail('test@e.com'); +true +> isEmail('test@e.com', {checkDNS: true, errorLevel: true}, log); +undefined +result 6 +> isEmail('test@e.com', {checkDNS: true, errorLevel: 7}, log); +undefined +result 0 +> isEmail('test@e.com', {checkDNS: true, errorLevel: 6}, log); +undefined +result 6 +``` + +TODO +==== + +Add tests for library usage, not just functionality comparisons. +Future versions will improve upon the current version, optimizing it for efficient usage and DRYing the code. + +License +======= + +[BSD License](http://www.opensource.org/licenses/bsd-license.php) + +[tests]: http://isemail.info/_system/is_email/test/?all "is_email test suite"
@@ -0,0 +1,1 @@
+module.exports = require('./lib/isemail');
@@ -0,0 +1,1394 @@
+/** + * To validate an email address according to RFCs 5321, 5322 and others + * + * Copyright © 2008-2011, Dominic Sayers + * Test schema documentation Copyright © 2011, Daniel Marschall + * Port for Node.js Copyright © 2013-2014, GlobeSherpa + * and Copyright © 2014-2015, Eli Skeggs + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of Dominic Sayers nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @author Dominic Sayers <dominic@sayers.cc> + * @author Eli Skeggs <skeggse@gmail.com> + * @copyright 2008-2011 Dominic Sayers + * @copyright 2013-2014 GlobeSherpa + * @copyright 2014-2015 Eli Skeggs + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @link http://www.dominicsayers.com/isemail + * @link https://github.com/hapijs/isemail + * @version 1.2.0 Drop Node 0.8, fix style, switch to lab/code + */ + +var Dns = require('dns'); + +var internals = { + defaultThreshold: 16, + maxIPv6Groups: 8, + categories: { + valid: 1, + dnsWarn: 7, + rfc5321: 15, + cfws: 31, + deprecated: 63, + rfc5322: 127, + error: 255 + }, + + diagnoses: { + // Address is valid + valid: 0, + + // Address is valid, but the DNS check failed + dnsWarnNoMXRecord: 5, + dnsWarnNoRecord: 6, + + // Address is valid for SMTP but has unusual elements + rfc5321TLD: 9, + rfc5321TLDNumeric: 10, + rfc5321QuotedString: 11, + rfc5321AddressLiteral: 12, + + // Address is valid for message, but must be modified for envelope + cfwsComment: 17, + cfwsFWS: 18, + + // Address contains deprecated elements, but may still be valid in some contexts + deprecatedLocalPart: 33, + deprecatedFWS: 34, + deprecatedQTEXT: 35, + deprecatedQP: 36, + deprecatedComment: 37, + deprecatedCTEXT: 38, + deprecatedIPv6: 39, + deprecatedCFWSNearAt: 49, + + // Address is only valid according to broad definition in RFC 5322, but is otherwise invalid + rfc5322Domain: 65, + rfc5322TooLong: 66, + rfc5322LocalTooLong: 67, + rfc5322DomainTooLong: 68, + rfc5322LabelTooLong: 69, + rfc5322DomainLiteral: 70, + rfc5322DomainLiteralOBSDText: 71, + rfc5322IPv6GroupCount: 72, + rfc5322IPv62x2xColon: 73, + rfc5322IPv6BadCharacter: 74, + rfc5322IPv6MaxGroups: 75, + rfc5322IPv6ColonStart: 76, + rfc5322IPv6ColonEnd: 77, + + // Address is invalid for any purpose + errExpectingDTEXT: 129, + errNoLocalPart: 130, + errNoDomain: 131, + errConsecutiveDots: 132, + errATEXTAfterCFWS: 133, + errATEXTAfterQS: 134, + errATEXTAfterDomainLiteral: 135, + errExpectingQPair: 136, + errExpectingATEXT: 137, + errExpectingQTEXT: 138, + errExpectingCTEXT: 139, + errBackslashEnd: 140, + errDotStart: 141, + errDotEnd: 142, + errDomainHyphenStart: 143, + errDomainHyphenEnd: 144, + errUnclosedQuotedString: 145, + errUnclosedComment: 146, + errUnclosedDomainLiteral: 147, + errFWSCRLFx2: 148, + errFWSCRLFEnd: 149, + errCRNoLF: 150, + errUnknownTLD: 160, + errDomainTooShort: 161 + }, + + components: { + localpart: 0, + domain: 1, + literal: 2, + contextComment: 3, + contextFWS: 4, + contextQuotedString: 5, + contextQuotedPair: 6 + } +}; + +// $lab:coverage:off$ +internals.defer = typeof process !== 'undefined' && process && typeof process.nextTick === 'function' ? + process.nextTick.bind(process) : + function (callback) { + + return setTimeout(callback, 0); + }; +// $lab:coverage:on$ + + +// US-ASCII visible characters not valid for atext +// (http://tools.ietf.org/html/rfc5322#section-3.2.3) +var SPECIALS = '()<>[]:;@\\,."'; + +// A silly little optimized function generator +var optimizeLookup = function optimizeLookup (string) { + + var lookup = new Array(0x100); + + for (var i = 0xff; i >= 0; --i) { + lookup[i] = false; + } + + for (var il = string.length; i < il; ++i) { + lookup[string.charCodeAt(i)] = true; + } + + var body = 'return function (code) {\n'; + body += ' return lookup[code];\n'; + body += '}'; + return (new Function('lookup', body))(lookup); +}; + + +var specialsLookup = optimizeLookup(SPECIALS); + +// This matches valid IPv4 addresses from the end of a string +var IPv4_REGEX = + /\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/; +var IPv6_REGEX = /^[a-fA-F\d]{0,4}$/; +var IPv6_REGEX_TEST = IPv6_REGEX.test.bind(IPv6_REGEX); + +var hasOwn = Object.prototype.hasOwnProperty; + +/** + * Check that an email address conforms to RFCs 5321, 5322 and others + * + * We distinguish clearly between a Mailbox as defined by RFC 5321 and an + * addr-spec as defined by RFC 5322. Depending on the context, either can be + * regarded as a valid email address. The RFC 5321 Mailbox specification is + * more restrictive (comments, white space and obsolete forms are not allowed). + * + * @param {string} email The email address to check. + * @param {Object} options The (optional) options: + * {boolean} checkDNS If true then will check DNS for MX records. If + * true this call to isEmail _will_ be asynchronous. + * {*} errorLevel Determines the boundary between valid and invalid + * addresses. Status codes above this number will be returned as-is, status + * codes below will be returned as valid. Thus the calling program can + * simply look for diagnoses.valid if it is only interested in whether an + * address is valid or not. The errorLevel will determine how "picky" + * isEmail() is about the address. If omitted or passed as false then + * isEmail() will return true or false rather than an integer error or + * warning. NB Note the difference between errorLevel = false and + * errorLevel = 0. + * @param {function(number|boolean)} callback The (optional) callback handler. + * @return {*} + */ +var isEmail = function isEmail (email, options, callback) { + + if (typeof options === 'function') { + callback = options; + options = {}; + } + + if (!options) { + options = {}; + } + + if (typeof callback !== 'function') { + if (options.checkDNS) { + throw new TypeError('expected callback function for checkDNS option'); + } + + callback = null; + } + + var diagnose; + var threshold; + + if (typeof options.errorLevel === 'number') { + diagnose = true; + threshold = options.errorLevel; + } + else { + diagnose = !!options.errorLevel; + threshold = internals.diagnoses.valid; + } + + if (options.tldWhitelist) { + if (typeof options.tldWhitelist === 'string') { + options.tldWhitelist = [options.tldWhitelist]; + } else if (typeof options.tldWhitelist !== 'object') { + throw new TypeError('expected array or object tldWhitelist'); + } + } + + if (options.minDomainAtoms && (options.minDomainAtoms !== ((+options.minDomainAtoms) | 0) || options.minDomainAtoms < 0)) { + throw new TypeError('expected positive integer minDomainAtoms'); + } + + var maxResult = internals.diagnoses.valid; + + var updateResult = function updateResult (value) { + + if (value > maxResult) { + maxResult = value; + } + }; + + var context = { + now: internals.components.localpart, + prev: internals.components.localpart, + stack: [internals.components.localpart] + }; + + var token; + var prevToken = ''; + var charCode = 0; + + var parseData = { + local: '', + domain: '' + }; + var atomData = { + locals: [''], + domains: [''] + }; + + var elementCount = 0; + var elementLength = 0; + var crlfCount = 0; + + var hyphenFlag = false; + var assertEnd = false; + + var emailLength = email.length; + + for (var i = 0, il = emailLength; i < il; ++i) { + // Token is used outside the loop, must declare similarly + token = email[i]; + + switch (context.now) { + // Local-part + case internals.components.localpart: + // http://tools.ietf.org/html/rfc5322#section-3.4.1 + // local-part = dot-atom / quoted-string / obs-local-part + // + // dot-atom = [CFWS] dot-atom-text [CFWS] + // + // dot-atom-text = 1*atext *("." 1*atext) + // + // quoted-string = [CFWS] + // DQUOTE *([FWS] qcontent) [FWS] DQUOTE + // [CFWS] + // + // obs-local-part = word *("." word) + // + // word = atom / quoted-string + // + // atom = [CFWS] 1*atext [CFWS] + switch (token) { + // Comment + case '(': + if (elementLength === 0) { + // Comments are OK at the beginning of an element + updateResult(elementCount === 0 ? internals.diagnoses.cfwsComment : internals.diagnoses.deprecatedComment); + } + else { + updateResult(internals.diagnoses.cfwsComment); + // Cannot start a comment in an element, should be end + assertEnd = true; + } + + context.stack.push(context.now); + context.now = internals.components.contextComment; + break; + + // Next dot-atom element + case '.': + if (elementLength === 0) { + // Another dot, already? + updateResult(elementCount === 0 ? internals.diagnoses.errDotStart : internals.diagnoses.errConsecutiveDots); + } + else { + // The entire local-part can be a quoted string for RFC 5321; if one atom is quoted it's an RFC 5322 obsolete form + if (assertEnd) { + updateResult(internals.diagnoses.deprecatedLocalPart); + } + + // CFWS & quoted strings are OK again now we're at the beginning of an element (although they are obsolete forms) + assertEnd = false; + elementLength = 0; + ++elementCount; + parseData.local += token; + atomData.locals[elementCount] = ''; + } + + break; + + // Quoted string + case '"': + if (elementLength === 0) { + // The entire local-part can be a quoted string for RFC 5321; if one atom is quoted it's an RFC 5322 obsolete form + updateResult(elementCount === 0 ? internals.diagnoses.rfc5321QuotedString : internals.diagnoses.deprecatedLocalPart); + + parseData.local += token; + atomData.locals[elementCount] += token; + ++elementLength; + + // Quoted string must be the entire element + assertEnd = true; + context.stack.push(context.now); + context.now = internals.components.contextQuotedString; + } + else { + updateResult(internals.diagnoses.errExpectingATEXT); + } + + break; + + // Folding white space + case '\r': + if (emailLength === ++i || email[i] !== '\n') { + // Fatal error + updateResult(internals.diagnoses.errCRNoLF); + break; + } + + // Fallthrough + + case ' ': + case '\t': + if (elementLength === 0) { + updateResult(elementCount === 0 ? internals.diagnoses.cfwsFWS : internals.diagnoses.deprecatedFWS); + } + else { + // We can't start FWS in the middle of an element, better be end + assertEnd = true; + } + + context.stack.push(context.now); + context.now = internals.components.contextFWS; + prevToken = token; + break; + + case '@': + // At this point we should have a valid local-part + // $lab:coverage:off$ + if (context.stack.length !== 1) { + throw new Error('unexpected item on context stack'); + } + // $lab:coverage:on$ + + if (parseData.local.length === 0) { + // Fatal error + updateResult(internals.diagnoses.errNoLocalPart); + } + else if (elementLength === 0) { + // Fatal error + updateResult(internals.diagnoses.errDotEnd); + } + // http://tools.ietf.org/html/rfc5321#section-4.5.3.1.1 the maximum total length of a user name or other local-part is 64 + // octets + else if (parseData.local.length > 64) { + updateResult(internals.diagnoses.rfc5322LocalTooLong); + } + // http://tools.ietf.org/html/rfc5322#section-3.4.1 comments and folding white space SHOULD NOT be used around "@" in the + // addr-spec + // + // http://tools.ietf.org/html/rfc2119 + // 4. SHOULD NOT this phrase, or the phrase "NOT RECOMMENDED" mean that there may exist valid reasons in particular + // circumstances when the particular behavior is acceptable or even useful, but the full implications should be understood + // and the case carefully weighed before implementing any behavior described with this label. + else if (context.prev === internals.components.contextComment || context.prev === internals.components.contextFWS) { + updateResult(internals.diagnoses.deprecatedCFWSNearAt); + } + + // Clear everything down for the domain parsing + context.now = internals.components.domain; + context.stack[0] = internals.components.domain; + elementCount = 0; + elementLength = 0; + assertEnd = false; // CFWS can only appear at the end of the element + break; + + // ATEXT + default: + // http://tools.ietf.org/html/rfc5322#section-3.2.3 + // atext = ALPHA / DIGIT / ; Printable US-ASCII + // "!" / "#" / ; characters not including + // "$" / "%" / ; specials. Used for atoms. + // "&" / "'" / + // "*" / "+" / + // "-" / "/" / + // "=" / "?" / + // "^" / "_" / + // "`" / "{" / + // "|" / "}" / + // "~" + if (assertEnd) { + // We have encountered atext where it is no longer valid + switch (context.prev) { + case internals.components.contextComment: + case internals.components.contextFWS: + updateResult(internals.diagnoses.errATEXTAfterCFWS); + break; + + case internals.components.contextQuotedString: + updateResult(internals.diagnoses.errATEXTAfterQS); + break; + + // $lab:coverage:off$ + default: + throw new Error('more atext found where none is allowed, but unrecognized prev context: ' + context.prev); + // $lab:coverage:on$ + } + } + else { + context.prev = context.now; + charCode = token.charCodeAt(0); + + // Especially if charCode == 10 + if (charCode < 33 || charCode > 126 || specialsLookup(charCode)) { + + // Fatal error + updateResult(internals.diagnoses.errExpectingATEXT); + } + + parseData.local += token; + atomData.locals[elementCount] += token; + ++elementLength; + } + } + + break; + + case internals.components.domain: + // http://tools.ietf.org/html/rfc5322#section-3.4.1 + // domain = dot-atom / domain-literal / obs-domain + // + // dot-atom = [CFWS] dot-atom-text [CFWS] + // + // dot-atom-text = 1*atext *("." 1*atext) + // + // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] + // + // dtext = %d33-90 / ; Printable US-ASCII + // %d94-126 / ; characters not including + // obs-dtext ; "[", "]", or "\" + // + // obs-domain = atom *("." atom) + // + // atom = [CFWS] 1*atext [CFWS] + + // http://tools.ietf.org/html/rfc5321#section-4.1.2 + // Mailbox = Local-part "@" ( Domain / address-literal ) + // + // Domain = sub-domain *("." sub-domain) + // + // address-literal = "[" ( IPv4-address-literal / + // IPv6-address-literal / + // General-address-literal ) "]" + // ; See Section 4.1.3 + + // http://tools.ietf.org/html/rfc5322#section-3.4.1 + // Note: A liberal syntax for the domain portion of addr-spec is + // given here. However, the domain portion contains addressing + // information specified by and used in other protocols (e.g., + // [RFC1034], [RFC1035], [RFC1123], [RFC5321]). It is therefore + // incumbent upon implementations to conform to the syntax of + // addresses for the context in which they are used. + // + // is_email() author's note: it's not clear how to interpret this in + // he context of a general email address validator. The conclusion I + // have reached is this: "addressing information" must comply with + // RFC 5321 (and in turn RFC 1035), anything that is "semantically + // invisible" must comply only with RFC 5322. + switch (token) { + // Comment + case '(': + if (elementLength === 0) { + // Comments at the start of the domain are deprecated in the text, comments at the start of a subdomain are obs-domain + // http://tools.ietf.org/html/rfc5322#section-3.4.1 + updateResult(elementCount === 0 ? internals.diagnoses.deprecatedCFWSNearAt : internals.diagnoses.deprecatedComment); + } + else { + // We can't start a comment mid-element, better be at the end + assertEnd = true; + updateResult(internals.diagnoses.cfwsComment); + } + + context.stack.push(context.now); + context.now = internals.components.contextComment; + break; + + // Next dot-atom element + case '.': + if (elementLength === 0) { + // Another dot, already? Fatal error. + updateResult(elementCount === 0 ? internals.diagnoses.errDotStart : internals.diagnoses.errConsecutiveDots); + } + else if (hyphenFlag) { + // Previous subdomain ended in a hyphen. Fatal error. + updateResult(internals.diagnoses.errDomainHyphenEnd); + } + else if (elementLength > 63) { + // Nowhere in RFC 5321 does it say explicitly that the domain part of a Mailbox must be a valid domain according to the + // DNS standards set out in RFC 1035, but this *is* implied in several places. For instance, wherever the idea of host + // routing is discussed the RFC says that the domain must be looked up in the DNS. This would be nonsense unless the + // domain was designed to be a valid DNS domain. Hence we must conclude that the RFC 1035 restriction on label length + // also applies to RFC 5321 domains. + // + // http://tools.ietf.org/html/rfc1035#section-2.3.4 + // labels 63 octets or less + + updateResult(internals.diagnoses.rfc5322LabelTooLong); + } + + // CFWS is OK again now we're at the beginning of an element (although + // it may be obsolete CFWS) + assertEnd = false; + elementLength = 0; + ++elementCount; + atomData.domains[elementCount] = ''; + parseData.domain += token; + + break; + + // Domain literal + case '[': + if (parseData.domain.length === 0) { + // Domain literal must be the only component + assertEnd = true; + ++elementLength; + context.stack.push(context.now); + context.now = internals.components.literal; + parseData.domain += token; + atomData.domains[elementCount] += token; + parseData.literal = ''; + } + else { + // Fatal error + updateResult(internals.diagnoses.errExpectingATEXT); + } + + break; + + // Folding white space + case '\r': + if (emailLength === ++i || email[i] !== '\n') { + // Fatal error + updateResult(internals.diagnoses.errCRNoLF); + break; + } + + // Fallthrough + + case ' ': + case '\t': + if (elementLength === 0) { + updateResult(elementCount === 0 ? internals.diagnoses.deprecatedCFWSNearAt : internals.diagnoses.deprecatedFWS); + } + else { + // We can't start FWS in the middle of an element, so this better be the end + updateResult(internals.diagnoses.cfwsFWS); + assertEnd = true; + } + + context.stack.push(context.now); + context.now = internals.components.contextFWS; + prevToken = token; + break; + + // This must be ATEXT + default: + // RFC 5322 allows any atext... + // http://tools.ietf.org/html/rfc5322#section-3.2.3 + // atext = ALPHA / DIGIT / ; Printable US-ASCII + // "!" / "#" / ; characters not including + // "$" / "%" / ; specials. Used for atoms. + // "&" / "'" / + // "*" / "+" / + // "-" / "/" / + // "=" / "?" / + // "^" / "_" / + // "`" / "{" / + // "|" / "}" / + // "~" + + // But RFC 5321 only allows letter-digit-hyphen to comply with DNS rules + // (RFCs 1034 & 1123) + // http://tools.ietf.org/html/rfc5321#section-4.1.2 + // sub-domain = Let-dig [Ldh-str] + // + // Let-dig = ALPHA / DIGIT + // + // Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig + // + if (assertEnd) { + // We have encountered ATEXT where it is no longer valid + switch (context.prev) { + case internals.components.contextComment: + case internals.components.contextFWS: + updateResult(internals.diagnoses.errATEXTAfterCFWS); + break; + + case internals.components.literal: + updateResult(internals.diagnoses.errATEXTAfterDomainLiteral); + break; + + // $lab:coverage:off$ + default: + throw new Error('more atext found where none is allowed, but unrecognized prev context: ' + context.prev); + // $lab:coverage:on$ + } + } + + charCode = token.charCodeAt(0); + // Assume this token isn't a hyphen unless we discover it is + hyphenFlag = false; + + if (charCode < 33 || charCode > 126 || specialsLookup(charCode)) { + // Fatal error + updateResult(internals.diagnoses.errExpectingATEXT); + } + else if (token === '-') { + if (elementLength === 0) { + // Hyphens cannot be at the beginning of a subdomain, fatal error + updateResult(internals.diagnoses.errDomainHyphenStart); + } + + hyphenFlag = true; + } + // Check if it's a neither a number nor a latin letter + else if (charCode < 48 || charCode > 122 || (charCode > 57 && charCode < 65) || (charCode > 90 && charCode < 97)) { + // This is not an RFC 5321 subdomain, but still OK by RFC 5322 + updateResult(internals.diagnoses.rfc5322Domain); + } + + parseData.domain += token; + atomData.domains[elementCount] += token; + ++elementLength; + } + + break; + + // Domain literal + case internals.components.literal: + // http://tools.ietf.org/html/rfc5322#section-3.4.1 + // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] + // + // dtext = %d33-90 / ; Printable US-ASCII + // %d94-126 / ; characters not including + // obs-dtext ; "[", "]", or "\" + // + // obs-dtext = obs-NO-WS-CTL / quoted-pair + switch (token) { + // End of domain literal + case ']': + if (maxResult < internals.categories.deprecated) { + // Could be a valid RFC 5321 address literal, so let's check + + // http://tools.ietf.org/html/rfc5321#section-4.1.2 + // address-literal = "[" ( IPv4-address-literal / + // IPv6-address-literal / + // General-address-literal ) "]" + // ; See Section 4.1.3 + // + // http://tools.ietf.org/html/rfc5321#section-4.1.3 + // IPv4-address-literal = Snum 3("." Snum) + // + // IPv6-address-literal = "IPv6:" IPv6-addr + // + // General-address-literal = Standardized-tag ":" 1*dcontent + // + // Standardized-tag = Ldh-str + // ; Standardized-tag MUST be specified in a + // ; Standards-Track RFC and registered with IANA + // + // dcontent = %d33-90 / ; Printable US-ASCII + // %d94-126 ; excl. "[", "\", "]" + // + // Snum = 1*3DIGIT + // ; representing a decimal integer + // ; value in the range 0 through 255 + // + // IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp + // + // IPv6-hex = 1*4HEXDIG + // + // IPv6-full = IPv6-hex 7(":" IPv6-hex) + // + // IPv6-comp = [IPv6-hex *5(":" IPv6-hex)] "::" + // [IPv6-hex *5(":" IPv6-hex)] + // ; The "::" represents at least 2 16-bit groups of + // ; zeros. No more than 6 groups in addition to the + // ; "::" may be present. + // + // IPv6v4-full = IPv6-hex 5(":" IPv6-hex) ":" IPv4-address-literal + // + // IPv6v4-comp = [IPv6-hex *3(":" IPv6-hex)] "::" + // [IPv6-hex *3(":" IPv6-hex) ":"] + // IPv4-address-literal + // ; The "::" represents at least 2 16-bit groups of + // ; zeros. No more than 4 groups in addition to the + // ; "::" and IPv4-address-literal may be present. + + var index = -1; + var addressLiteral = parseData.literal; + var matchesIP = IPv4_REGEX.exec(addressLiteral); + + // Maybe extract IPv4 part from the end of the address-literal + if (matchesIP) { + index = matchesIP.index; + if (index !== 0) { + // Convert IPv4 part to IPv6 format for futher testing + addressLiteral = addressLiteral.slice(0, index) + '0:0'; + } + } + + if (index === 0) { + // Nothing there except a valid IPv4 address, so... + updateResult(internals.diagnoses.rfc5321AddressLiteral); + } + else if (addressLiteral.slice(0, 5).toLowerCase() !== 'ipv6:') { + updateResult(internals.diagnoses.rfc5322DomainLiteral); + } + else { + var match = addressLiteral.slice(5); + var maxGroups = internals.maxIPv6Groups; + var groups = match.split(':'); + index = match.indexOf('::'); + + if (!~index) { + // Need exactly the right number of groups + if (groups.length !== maxGroups) { + updateResult(internals.diagnoses.rfc5322IPv6GroupCount); + } + } + else if (index !== match.lastIndexOf('::')) { + updateResult(internals.diagnoses.rfc5322IPv62x2xColon); + } + else { + if (index === 0 || index === match.length - 2) { + // RFC 4291 allows :: at the start or end of an address with 7 other groups in addition + ++maxGroups; + } + + if (groups.length > maxGroups) { + updateResult(internals.diagnoses.rfc5322IPv6MaxGroups); + } + else if (groups.length === maxGroups) { + // Eliding a single "::" + updateResult(internals.diagnoses.deprecatedIPv6); + } + } + + // IPv6 testing strategy + if (match[0] === ':' && match[1] !== ':') { + updateResult(internals.diagnoses.rfc5322IPv6ColonStart); + } + else if (match[match.length - 1] === ':' && match[match.length - 2] !== ':') { + updateResult(internals.diagnoses.rfc5322IPv6ColonEnd); + } + else if (groups.every(IPv6_REGEX_TEST)) { + updateResult(internals.diagnoses.rfc5321AddressLiteral); + } + else { + updateResult(internals.diagnoses.rfc5322IPv6BadCharacter); + } + } + } + else { + updateResult(internals.diagnoses.rfc5322DomainLiteral); + } + + parseData.domain += token; + atomData.domains[elementCount] += token; + ++elementLength; + context.prev = context.now; + context.now = context.stack.pop(); + break; + + case '\\': + updateResult(internals.diagnoses.rfc5322DomainLiteralOBSDText); + context.stack.push(context.now); + context.now = internals.components.contextQuotedPair; + break; + + // Folding white space + case '\r': + if (emailLength === ++i || email[i] !== '\n') { + updateResult(internals.diagnoses.errCRNoLF); + break; + } + + // Fallthrough + + case ' ': + case '\t': + updateResult(internals.diagnoses.cfwsFWS); + + context.stack.push(context.now); + context.now = internals.components.contextFWS; + prevToken = token; + break; + + // DTEXT + default: + // http://tools.ietf.org/html/rfc5322#section-3.4.1 + // dtext = %d33-90 / ; Printable US-ASCII + // %d94-126 / ; characters not including + // obs-dtext ; "[", "]", or "\" + // + // obs-dtext = obs-NO-WS-CTL / quoted-pair + // + // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control + // %d11 / ; characters that do not + // %d12 / ; include the carriage + // %d14-31 / ; return, line feed, and + // %d127 ; white space characters + charCode = token.charCodeAt(0); + + // '\r', '\n', ' ', and '\t' have already been parsed above + if (charCode > 127 || charCode === 0 || token === '[') { + // Fatal error + updateResult(internals.diagnoses.errExpectingDTEXT); + break; + } + else if (charCode < 33 || charCode === 127) { + updateResult(internals.diagnoses.rfc5322DomainLiteralOBSDText); + } + + parseData.literal += token; + parseData.domain += token; + atomData.domains[elementCount] += token; + ++elementLength; + } + + break; + + // Quoted string + case internals.components.contextQuotedString: + // http://tools.ietf.org/html/rfc5322#section-3.2.4 + // quoted-string = [CFWS] + // DQUOTE *([FWS] qcontent) [FWS] DQUOTE + // [CFWS] + // + // qcontent = qtext / quoted-pair + switch (token) { + // Quoted pair + case '\\': + context.stack.push(context.now); + context.now = internals.components.contextQuotedPair; + break; + + // Folding white space. Spaces are allowed as regular characters inside a quoted string - it's only FWS if we include '\t' or '\r\n' + case '\r': + if (emailLength === ++i || email[i] !== '\n') { + // Fatal error + updateResult(internals.diagnoses.errCRNoLF); + break; + } + + // Fallthrough + + case '\t': + // http://tools.ietf.org/html/rfc5322#section-3.2.2 + // Runs of FWS, comment, or CFWS that occur between lexical tokens in + // a structured header field are semantically interpreted as a single + // space character. + + // http://tools.ietf.org/html/rfc5322#section-3.2.4 + // the CRLF in any FWS/CFWS that appears within the quoted-string [is] + // semantically "invisible" and therefore not part of the + // quoted-string + + parseData.local += ' '; + atomData.locals[elementCount] += ' '; + ++elementLength; + + updateResult(internals.diagnoses.cfwsFWS); + context.stack.push(context.now); + context.now = internals.components.contextFWS; + prevToken = token; + break; + + // End of quoted string + case '"': + parseData.local += token; + atomData.locals[elementCount] += token; + ++elementLength; + context.prev = context.now; + context.now = context.stack.pop(); + break; + + // QTEXT + default: + // http://tools.ietf.org/html/rfc5322#section-3.2.4 + // qtext = %d33 / ; Printable US-ASCII + // %d35-91 / ; characters not including + // %d93-126 / ; "\" or the quote character + // obs-qtext + // + // obs-qtext = obs-NO-WS-CTL + // + // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control + // %d11 / ; characters that do not + // %d12 / ; include the carriage + // %d14-31 / ; return, line feed, and + // %d127 ; white space characters + charCode = token.charCodeAt(0); + + if (charCode > 127 || charCode === 0 || charCode === 10) { + updateResult(internals.diagnoses.errExpectingQTEXT); + } + else if (charCode < 32 || charCode === 127) { + updateResult(internals.diagnoses.deprecatedQTEXT); + } + + parseData.local += token; + atomData.locals[elementCount] += token; + ++elementLength; + } + + // http://tools.ietf.org/html/rfc5322#section-3.4.1 + // If the string can be represented as a dot-atom (that is, it contains + // no characters other than atext characters or "." surrounded by atext + // characters), then the dot-atom form SHOULD be used and the quoted- + // string form SHOULD NOT be used. + + break; + // Quoted pair + case internals.components.contextQuotedPair: + // http://tools.ietf.org/html/rfc5322#section-3.2.1 + // quoted-pair = ("\" (VCHAR / WSP)) / obs-qp + // + // VCHAR = %d33-126 ; visible (printing) characters + // WSP = SP / HTAB ; white space + // + // obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) + // + // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control + // %d11 / ; characters that do not + // %d12 / ; include the carriage + // %d14-31 / ; return, line feed, and + // %d127 ; white space characters + // + // i.e. obs-qp = "\" (%d0-8, %d10-31 / %d127) + charCode = token.charCodeAt(0); + + if (charCode > 127) { + // Fatal error + updateResult(internals.diagnoses.errExpectingQPair); + } + else if ((charCode < 31 && charCode !== 9) || charCode === 127) { + // ' ' and '\t' are allowed + updateResult(internals.diagnoses.deprecatedQP); + } + + // At this point we know where this qpair occurred so we could check to see if the character actually needed to be quoted at all. + // http://tools.ietf.org/html/rfc5321#section-4.1.2 + // the sending system SHOULD transmit the form that uses the minimum quoting possible. + + context.prev = context.now; + // End of qpair + context.now = context.stack.pop(); + token = '\\' + token; + + switch (context.now) { + case internals.components.contextComment: + break; + + case internals.components.contextQuotedString: + parseData.local += token; + atomData.locals[elementCount] += token; + + // The maximum sizes specified by RFC 5321 are octet counts, so we must include the backslash + elementLength += 2; + break; + + case internals.components.literal: + parseData.domain += token; + atomData.domains[elementCount] += token; + + // The maximum sizes specified by RFC 5321 are octet counts, so we must include the backslash + elementLength += 2; + break; + + // $lab:coverage:off$ + default: + throw new Error('quoted pair logic invoked in an invalid context: ' + context.now); + // $lab:coverage:on$ + } + break; + + // Comment + case internals.components.contextComment: + // http://tools.ietf.org/html/rfc5322#section-3.2.2 + // comment = "(" *([FWS] ccontent) [FWS] ")" + // + // ccontent = ctext / quoted-pair / comment + switch (token) { + // Nested comment + case '(': + // Nested comments are ok + context.stack.push(context.now); + context.now = internals.components.contextComment; + break; + + // End of comment + case ')': + context.prev = context.now; + context.now = context.stack.pop(); + break; + + // Quoted pair + case '\\': + context.stack.push(context.now); + context.now = internals.components.contextQuotedPair; + break; + + // Folding white space + case '\r': + if (emailLength === ++i || email[i] !== '\n') { + // Fatal error + updateResult(internals.diagnoses.errCRNoLF); + break; + } + + // Fallthrough + + case ' ': + case '\t': + updateResult(internals.diagnoses.cfwsFWS); + + context.stack.push(context.now); + context.now = internals.components.contextFWS; + prevToken = token; + break; + + // CTEXT + default: + // http://tools.ietf.org/html/rfc5322#section-3.2.3 + // ctext = %d33-39 / ; Printable US-ASCII + // %d42-91 / ; characters not including + // %d93-126 / ; "(", ")", or "\" + // obs-ctext + // + // obs-ctext = obs-NO-WS-CTL + // + // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control + // %d11 / ; characters that do not + // %d12 / ; include the carriage + // %d14-31 / ; return, line feed, and + // %d127 ; white space characters + charCode = token.charCodeAt(0); + + if (charCode > 127 || charCode === 0 || charCode === 10) { + // Fatal error + updateResult(internals.diagnoses.errExpectingCTEXT); + break; + } + else if (charCode < 32 || charCode === 127) { + updateResult(internals.diagnoses.deprecatedCTEXT); + } + } + + break; + + // Folding white space + case internals.components.contextFWS: + // http://tools.ietf.org/html/rfc5322#section-3.2.2 + // FWS = ([*WSP CRLF] 1*WSP) / obs-FWS + // ; Folding white space + + // But note the erratum: + // http://www.rfc-editor.org/errata_search.php?rfc=5322&eid=1908: + // In the obsolete syntax, any amount of folding white space MAY be + // inserted where the obs-FWS rule is allowed. This creates the + // possibility of having two consecutive "folds" in a line, and + // therefore the possibility that a line which makes up a folded header + // field could be composed entirely of white space. + // + // obs-FWS = 1*([CRLF] WSP) + + if (prevToken === '\r') { + if (token === '\r') { + // Fatal error + updateResult(internals.diagnoses.errFWSCRLFx2); + break; + } + + if (++crlfCount > 1) { + // Multiple folds => obsolete FWS + updateResult(internals.diagnoses.deprecatedFWS); + } + else { + crlfCount = 1; + } + } + + switch (token) { + case '\r': + if (emailLength === ++i || email[i] !== '\n') { + // Fatal error + updateResult(internals.diagnoses.errCRNoLF); + } + + break; + + case ' ': + case '\t': + break; + + default: + if (prevToken === '\r') { + // Fatal error + updateResult(internals.diagnoses.errFWSCRLFEnd); + } + + crlfCount = 0; + + // End of FWS + context.prev = context.now; + context.now = context.stack.pop(); + + // Look at this token again in the parent context + --i; + } + + prevToken = token; + break; + + // Unexpected context + // $lab:coverage:off$ + default: + throw new Error('unknown context: ' + context.now); + // $lab:coverage:on$ + } // Primary state machine + + if (maxResult > internals.categories.rfc5322) { + // Fatal error, no point continuing + break; + } + } // Token loop + + // Check for errors + if (maxResult < internals.categories.rfc5322) { + // Fatal errors + if (context.now === internals.components.contextQuotedString) { + updateResult(internals.diagnoses.errUnclosedQuotedString); + } + else if (context.now === internals.components.contextQuotedPair) { + updateResult(internals.diagnoses.errBackslashEnd); + } + else if (context.now === internals.components.contextComment) { + updateResult(internals.diagnoses.errUnclosedComment); + } + else if (context.now === internals.components.literal) { + updateResult(internals.diagnoses.errUnclosedDomainLiteral); + } + else if (token === '\r') { + updateResult(internals.diagnoses.errFWSCRLFEnd); + } + else if (parseData.domain.length === 0) { + updateResult(internals.diagnoses.errNoDomain); + } + else if (elementLength === 0) { + updateResult(internals.diagnoses.errDotEnd); + } + else if (hyphenFlag) { + updateResult(internals.diagnoses.errDomainHyphenEnd); + } + + // Other errors + else if (parseData.domain.length > 255) { + // http://tools.ietf.org/html/rfc5321#section-4.5.3.1.2 + // The maximum total length of a domain name or number is 255 octets. + updateResult(internals.diagnoses.rfc5322DomainTooLong); + } + else if (parseData.local.length + parseData.domain.length + /* '@' */ 1 > 254) { + // http://tools.ietf.org/html/rfc5321#section-4.1.2 + // Forward-path = Path + // + // Path = "<" [ A-d-l ":" ] Mailbox ">" + // + // http://tools.ietf.org/html/rfc5321#section-4.5.3.1.3 + // The maximum total length of a reverse-path or forward-path is 256 octets (including the punctuation and element separators). + // + // Thus, even without (obsolete) routing information, the Mailbox can only be 254 characters long. This is confirmed by this verified + // erratum to RFC 3696: + // + // http://www.rfc-editor.org/errata_search.php?rfc=3696&eid=1690 + // However, there is a restriction in RFC 2821 on the length of an address in MAIL and RCPT commands of 254 characters. Since + // addresses that do not fit in those fields are not normally useful, the upper limit on address lengths should normally be considered + // to be 254. + updateResult(internals.diagnoses.rfc5322TooLong); + } + else if (elementLength > 63) { + // http://tools.ietf.org/html/rfc1035#section-2.3.4 + // labels 63 octets or less + updateResult(internals.diagnoses.rfc5322LabelTooLong); + } + else if (options.minDomainAtoms && atomData.domains.length < options.minDomainAtoms) { + updateResult(internals.diagnoses.errDomainTooShort); + } + else if (options.tldWhitelist) { + var tldAtom = atomData.domains[elementCount]; + if (Array.isArray(options.tldWhitelist)) { + var tldValid = false; + for (i = 0, il = options.tldWhitelist.length; i < il; ++i) { + if (tldAtom === options.tldWhitelist[i]) { + tldValid = true; + break; + } + } + + if (!tldValid) { + updateResult(internals.diagnoses.errUnknownTLD); + } + } + else if (!hasOwn.call(options.tldWhitelist, tldAtom)) { + updateResult(internals.diagnoses.errUnknownTLD); + } + } + } // Check for errors + + var dnsPositive = false; + var finishImmediately = false; + + var finish = function finish () { + + if (!dnsPositive && maxResult < internals.categories.dnsWarn) { + // Per RFC 5321, domain atoms are limited to letter-digit-hyphen, so we only need to check code <= 57 to check for a digit + var code = atomData.domains[elementCount].charCodeAt(0); + if (code <= 57) { + updateResult(internals.diagnoses.rfc5321TLDNumeric); + } + else if (elementCount === 0) { + updateResult(internals.diagnoses.rfc5321TLD); + } + } + + if (maxResult < threshold) { + maxResult = internals.diagnoses.valid; + } + + var finishResult = diagnose ? maxResult : maxResult < internals.defaultThreshold; + + if (callback) { + if (finishImmediately) { + callback(finishResult); + } else { + internals.defer(callback.bind(null, finishResult)); + } + } + + return finishResult; + }; // Finish + + if (options.checkDNS && maxResult < internals.categories.dnsWarn) { + // http://tools.ietf.org/html/rfc5321#section-2.3.5 + // Names that can be resolved to MX RRs or address (i.e., A or AAAA) RRs (as discussed in Section 5) are permitted, as are CNAME RRs whose + // targets can be resolved, in turn, to MX or address RRs. + // + // http://tools.ietf.org/html/rfc5321#section-5.1 + // The lookup first attempts to locate an MX record associated with the name. If a CNAME record is found, the resulting name is processed + // as if it were the initial name. ... If an empty list of MXs is returned, the address is treated as if it was associated with an implicit + // MX RR, with a preference of 0, pointing to that host. + // + // isEmail() author's note: We will regard the existence of a CNAME to be sufficient evidence of the domain's existence. For performance + // reasons we will not repeat the DNS lookup for the CNAME's target, but we will raise a warning because we didn't immediately find an MX + // record. + if (elementCount === 0) { + // Checking TLD DNS only works if you explicitly check from the root + parseData.domain += '.'; + } + + var dnsDomain = parseData.domain; + Dns.resolveMx(dnsDomain, function resolveDNS (err, mxRecords) { + + // If we have a fatal error, then we must assume that there are no records + if (err && err.code !== Dns.NODATA) { + updateResult(internals.diagnoses.dnsWarnNoRecord); + return finish(); + } + + if (mxRecords && mxRecords.length) { + dnsPositive = true; + return finish(); + } + + var count = 3; + var done = false; + updateResult(internals.diagnoses.dnsWarnNoMXRecord); + + var handleRecords = function handleRecords (err, records) { + + if (done) { + return; + } + + --count; + + if (records && records.length) { + done = true; + return finish(); + } + + if (count === 0) { + // No usable records for the domain can be found + updateResult(internals.diagnoses.dnsWarnNoRecord); + done = true; + finish(); + } + }; + + Dns.resolveCname(dnsDomain, handleRecords); + Dns.resolve4(dnsDomain, handleRecords); + Dns.resolve6(dnsDomain, handleRecords); + }); + + finishImmediately = true; + } + else { + var result = finish(); + finishImmediately = true; + return result; + } // CheckDNS +}; + + +isEmail.diagnoses = (function exportDiagnoses () { + + var diag = {}; + for (var key in internals.diagnoses) { + diag[key] = internals.diagnoses[key]; + } + return diag; +})(); + +module.exports = isEmail;
@@ -0,0 +1,62 @@
+{ + "name": "isemail", + "version": "1.2.0", + "author": { + "name": "Eli Skeggs", + "email": "skeggse@gmail.com" + }, + "description": "validate an email address according to RFCs 5321, 5322, and others", + "main": "./index", + "scripts": { + "test": "lab -r console -o stdout -r lcov -o coverage.lcov -a code -L", + "test-cov-html": "lab -r html -o coverage.html -a code" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/hapijs/isemail.git" + }, + "homepage": "https://github.com/hapijs/isemail", + "bugs": { + "url": "https://github.com/hapijs/isemail/issues" + }, + "keywords": [ + "isemail", + "validation", + "check", + "checking", + "verification", + "email", + "address", + "email address" + ], + "devDependencies": { + "code": "^1.5.0", + "lab": "^5.16.1" + }, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10" + }, + "gitHead": "9441961a6c9979dc0e339971b111e25dc1a5b2fd", + "_id": "isemail@1.2.0", + "_shasum": "be03df8cc3e29de4d2c5df6501263f1fa4595e9a", + "_from": "isemail@>=1.0.0 <2.0.0", + "_npmVersion": "2.14.2", + "_nodeVersion": "4.0.0", + "_npmUser": { + "name": "skeggse", + "email": "skeggse@gmail.com" + }, + "dist": { + "shasum": "be03df8cc3e29de4d2c5df6501263f1fa4595e9a", + "tarball": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz" + }, + "maintainers": [ + { + "name": "skeggse", + "email": "skeggse@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz" +}
@@ -0,0 +1,175 @@
+var Lab = require('lab'); +var Code = require('code'); +var IsEmail = require('..'); +var Tests = require('./tests.json'); + +var internals = { + defaultThreshold: 16 +}; + +// Test shortcuts +var isEmail = IsEmail; +var lab = exports.lab = Lab.script(); +var before = lab.before; +var after = lab.after; +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + +// Diagnoses +var diag = isEmail.diagnoses; + +// Expectations +var expectations = Tests.map(function mapper (value) { + + value[1] = diag[value[1]]; + return value; +}); + +// Null characters aren't supported in JSON +expectations.push(['test@[\0', diag.errExpectingDTEXT]); +expectations.push(['(\0)test@example.com', diag.errExpectingCTEXT]); + +var tldExpectations = [ + ['shouldbe@invalid', diag.errUnknownTLD], + ['shouldbe@example.com', diag.valid] +]; + +describe('isEmail', function () { + + it('should check options.tldWhitelist', function (done) { + + expect(isEmail('person@top', { + tldWhitelist: 'top', + checkDNS: false + })).to.equal(true); + + expect(isEmail('person@top', { + tldWhitelist: ['com'], + checkDNS: false + })).to.equal(false); + + expect(function () { + + isEmail('', { + tldWhitelist: 77 + }); + }).to.throw(/tldWhitelist/); + done(); + }); + + it('should check options.minDomainAtoms', function (done) { + + expect(function () { + + isEmail('person@top', { + minDomainAtoms: -1 + }); + }).to.throw(/minDomainAtoms/); + + expect(function () { + + isEmail('person@top', { + minDomainAtoms: 1.5 + }); + }).to.throw(/minDomainAtoms/); + done(); + }); + + it('should use options.errorLevel', function (done) { + + expect(isEmail('person@123', { + errorLevel: diag.rfc5321TLDNumeric + 1 + })).to.equal(0); + + expect(isEmail('person@123', { + errorLevel: diag.rfc5321TLDNumeric + })).to.equal(diag.rfc5321TLDNumeric); + done(); + }); + + it('should ensure callback provided with checkDNS', function (done) { + + expect(function () { + + isEmail('person@top', { + checkDNS: true + }); + }).to.throw(/(?=.*\bcheckDNS\b)(?=.*\bcallback\b)/); + done(); + }); + + it('should handle omitted options', function (done) { + + expect(isEmail(expectations[0][0])).to.equal(expectations[0][1] < internals.defaultThreshold); + done(); + }); + + it('should handle omitted options with callback', function (done) { + + isEmail(expectations[0][0], function (res) { + + expect(res).to.equal(expectations[0][1] < internals.defaultThreshold); + done(); + }); + }); + + expectations.forEach(function (obj, i) { + + var email = obj[0], result = obj[1]; + it('should handle test ' + (i + 1), function (done) { + + isEmail(email, { + errorLevel: 0, + checkDNS: true + }, function (res) { + + expect(res).to.equal(result); + done(); + }); + }); + }); + + tldExpectations.forEach(function (obj, i) { + + var email = obj[0]; + var result = obj[1]; + + it('should handle tld test ' + (i + 1), function (done) { + + expect(isEmail(email, { + errorLevel: 0, + tldWhitelist: { + com: true + } + })).to.equal(result); + + expect(isEmail(email, { + errorLevel: 0, + tldWhitelist: ['com'] + })).to.equal(result); + + done(); + }); + }); + + it('should handle domain atom test 1', function (done) { + + expect(isEmail('shouldbe@invalid', { + errorLevel: 0, + minDomainAtoms: 2 + })).to.equal(diag.errDomainTooShort); + + done(); + }); + + it('should handle domain atom test 2', function (done) { + + expect(isEmail('valid@example.com', { + errorLevel: 0, + minDomainAtoms: 2 + })).to.equal(diag.valid); + + done(); + }); +});
@@ -0,0 +1,2 @@
+--reporter dot +--check-leaks
@@ -0,0 +1,187 @@
+[ + ["", "errNoDomain"], + ["\r", "errCRNoLF"], + ["test", "errNoDomain"], + ["@", "errNoLocalPart"], + ["test@", "errNoDomain"], + ["test@io", "valid"], + ["@io", "errNoLocalPart"], + ["@iana.org", "errNoLocalPart"], + ["test@iana.org", "valid"], + ["test@nominet.org.uk", "valid"], + ["test@about.museum", "valid"], + ["a@iana.org", "valid"], + ["test@e.com", "dnsWarnNoRecord"], + ["test@iana.a", "dnsWarnNoRecord"], + ["test.test@iana.org", "valid"], + [".test@iana.org", "errDotStart"], + ["test.@iana.org", "errDotEnd"], + ["test..iana.org", "errConsecutiveDots"], + ["test_exa-mple.com", "errNoDomain"], + ["!#$%&`*+/=?^`{|}~@iana.org", "valid"], + ["test\\@test@iana.org", "errExpectingATEXT"], + ["123@iana.org", "valid"], + ["test@123.com", "valid"], + ["test@iana.123", "rfc5321TLDNumeric"], + ["test@255.255.255.255", "rfc5321TLDNumeric"], + ["abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm@iana.org", "valid"], + ["abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklmn@iana.org", "rfc5322LocalTooLong"], + ["test@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm", "rfc5322LabelTooLong"], + ["test@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.com", "dnsWarnNoRecord"], + ["test@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm.com", "rfc5322LabelTooLong"], + ["test@mason-dixon.com", "valid"], + ["test@-iana.org", "errDomainHyphenStart"], + ["test@iana-.com", "errDomainHyphenEnd"], + ["test@iana.co-uk", "dnsWarnNoRecord"], + ["test@.iana.org", "errDotStart"], + ["test@iana.org.", "errDotEnd"], + ["test@iana..com", "errConsecutiveDots"], + ["a@a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v", "dnsWarnNoRecord"], + ["abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi", "dnsWarnNoRecord"], + ["abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij", "rfc5322TooLong"], + ["a@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg.hij", "rfc5322TooLong"], + ["a@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg.hijk", "rfc5322DomainTooLong"], + ["\"\r", "errCRNoLF"], + ["\"test\"@iana.org", "rfc5321QuotedString"], + ["\"\"@iana.org", "rfc5321QuotedString"], + ["\"\"\"@iana.org", "errExpectingATEXT"], + ["\"\\a\"@iana.org", "rfc5321QuotedString"], + ["\"\\\"\"@iana.org", "rfc5321QuotedString"], + ["\"\\\"@iana.org", "errUnclosedQuotedString"], + ["\"\\\\\"@iana.org", "rfc5321QuotedString"], + ["test\"@iana.org", "errExpectingATEXT"], + ["\"test@iana.org", "errUnclosedQuotedString"], + ["\"test\"test@iana.org", "errATEXTAfterQS"], + ["test\"text\"@iana.org", "errExpectingATEXT"], + ["\"test\"\"test\"@iana.org", "errExpectingATEXT"], + ["\"test\".\"test\"@iana.org", "deprecatedLocalPart"], + ["\"test\\ test\"@iana.org", "rfc5321QuotedString"], + ["\"test\".test@iana.org", "deprecatedLocalPart"], + ["\"test\u0000\"@iana.org", "errExpectingQTEXT"], + ["\"test\\\u0000\"@iana.org", "deprecatedQP"], + ["\"test\r\n test\"@iana.org", "cfwsFWS"], + ["\"abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghj\"@iana.org", "rfc5322LocalTooLong"], + ["\"abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefg\\h\"@iana.org", "rfc5322LocalTooLong"], + ["test@[255.255.255.255]", "rfc5321AddressLiteral"], + ["test@a[255.255.255.255]", "errExpectingATEXT"], + ["test@[255.255.255]", "rfc5322DomainLiteral"], + ["test@[255.255.255.255.255]", "rfc5322DomainLiteral"], + ["test@[255.255.255.256]", "rfc5322DomainLiteral"], + ["test@[1111:2222:3333:4444:5555:6666:7777:8888]", "rfc5322DomainLiteral"], + ["test@[IPv6:1111:2222:3333:4444:5555:6666:7777]", "rfc5322IPv6GroupCount"], + ["test@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888]", "rfc5321AddressLiteral"], + ["test@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888:9999]", "rfc5322IPv6GroupCount"], + ["test@[IPv6:1111:2222:3333:4444:5555:6666:7777:888G]", "rfc5322IPv6BadCharacter"], + ["test@[IPv6:1111:2222:3333:4444:5555:6666::8888]", "deprecatedIPv6"], + ["test@[IPv6:1111:2222:3333:4444:5555::8888]", "rfc5321AddressLiteral"], + ["test@[IPv6:1111:2222:3333:4444:5555:6666::7777:8888]", "rfc5322IPv6MaxGroups"], + ["test@[IPv6::3333:4444:5555:6666:7777:8888]", "rfc5322IPv6ColonStart"], + ["test@[IPv6:::3333:4444:5555:6666:7777:8888]", "rfc5321AddressLiteral"], + ["test@[IPv6:1111::4444:5555::8888]", "rfc5322IPv62x2xColon"], + ["test@[IPv6:::]", "rfc5321AddressLiteral"], + ["test@[IPv6:1111:2222:3333:4444:5555:255.255.255.255]", "rfc5322IPv6GroupCount"], + ["test@[IPv6:1111:2222:3333:4444:5555:6666:255.255.255.255]", "rfc5321AddressLiteral"], + ["test@[IPv6:1111:2222:3333:4444:5555:6666:7777:255.255.255.255]", "rfc5322IPv6GroupCount"], + ["test@[IPv6:1111:2222:3333:4444::255.255.255.255]", "rfc5321AddressLiteral"], + ["test@[IPv6:1111:2222:3333:4444:5555:6666::255.255.255.255]", "rfc5322IPv6MaxGroups"], + ["test@[IPv6:1111:2222:3333:4444:::255.255.255.255]", "rfc5322IPv62x2xColon"], + ["test@[IPv6::255.255.255.255]", "rfc5322IPv6ColonStart"], + [" test @iana.org", "deprecatedCFWSNearAt"], + ["test@ iana .com", "deprecatedCFWSNearAt"], + ["test . test@iana.org", "deprecatedFWS"], + ["\r\n test@iana.org", "cfwsFWS"], + ["\r\n \r\n test@iana.org", "deprecatedFWS"], + ["(\r", "errCRNoLF"], + ["(comment)test@iana.org", "cfwsComment"], + ["((comment)test@iana.org", "errUnclosedComment"], + ["(comment(comment))test@iana.org", "cfwsComment"], + ["test@(comment)iana.org", "deprecatedCFWSNearAt"], + ["test(comment)@iana.org", "deprecatedCFWSNearAt"], + ["test(comment)test@iana.org", "errATEXTAfterCFWS"], + ["test@(comment)[255.255.255.255]", "deprecatedCFWSNearAt"], + ["(comment)abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm@iana.org", "cfwsComment"], + ["test@(comment)abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.com", "deprecatedCFWSNearAt"], + ["(comment)test@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghik.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghik.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstu", "cfwsComment"], + ["test@iana.org\n", "errExpectingATEXT"], + ["test@xn--hxajbheg2az3al.xn--jxalpdlp", "dnsWarnNoRecord"], + ["xn--test@iana.org", "valid"], + ["test@iana.org-", "errDomainHyphenEnd"], + ["\"test@iana.org", "errUnclosedQuotedString"], + ["(test@iana.org", "errUnclosedComment"], + ["test@(iana.org", "errUnclosedComment"], + ["test@[1.2.3.4", "errUnclosedDomainLiteral"], + ["\"test\\\"@iana.org", "errUnclosedQuotedString"], + ["(comment\\)test@iana.org", "errUnclosedComment"], + ["test@iana.org(comment\\)", "errUnclosedComment"], + ["test@iana.org(comment\\", "errBackslashEnd"], + ["test@[RFC-5322-domain-literal]", "rfc5322DomainLiteral"], + ["test@[RFC-5322]-domain-literal]", "errATEXTAfterDomainLiteral"], + ["test@[RFC-5322-[domain-literal]", "errExpectingDTEXT"], + ["test@[", "errExpectingDTEXT"], + ["test@[\u0007]", "rfc5322DomainLiteralOBSDText"], + ["test@[RFC-5322-\\\u0007-domain-literal]", "rfc5322DomainLiteralOBSDText"], + ["test@[RFC-5322-\\\t-domain-literal]", "rfc5322DomainLiteralOBSDText"], + ["test@[RFC-5322-\\]-domain-literal]", "rfc5322DomainLiteralOBSDText"], + ["test@[RFC-5322--domain-literal]", "rfc5322DomainLiteralOBSDText"], + ["test@[RFC-5322-domain-literal\\]", "errUnclosedDomainLiteral"], + ["test@[RFC-5322-domain-literal\\", "errBackslashEnd"], + ["test@[RFC 5322 domain literal]", "rfc5322DomainLiteral"], + ["test@[RFC-5322-domain-literal] (comment)", "rfc5322DomainLiteral"], + ["@iana.org", "errExpectingATEXT"], + ["test@.org", "errExpectingATEXT"], + ["\"\"@iana.org", "deprecatedQTEXT"], + ["\"\"@iana.org", "errExpectingQTEXT"], + ["\"\\\"@iana.org", "deprecatedQP"], + ["()test@iana.org", "deprecatedCTEXT"], + ["()test@iana.org", "errExpectingCTEXT"], + ["test@iana.org\r", "errCRNoLF"], + ["\rtest@iana.org", "errCRNoLF"], + ["\"\rtest\"@iana.org", "errCRNoLF"], + ["(\r)test@iana.org", "errCRNoLF"], + ["test@iana.org(\r)", "errCRNoLF"], + ["\ntest@iana.org", "errExpectingATEXT"], + ["\"\n\"@iana.org", "errExpectingQTEXT"], + ["\"\\\n\"@iana.org", "deprecatedQP"], + ["(\n)test@iana.org", "errExpectingCTEXT"], + ["\u0007@iana.org", "errExpectingATEXT"], + ["test@\u0007.org", "errExpectingATEXT"], + ["\"\u0007\"@iana.org", "deprecatedQTEXT"], + ["\"\\\u0007\"@iana.org", "deprecatedQP"], + ["(\u0007)test@iana.org", "deprecatedCTEXT"], + ["\r\ntest@iana.org", "errFWSCRLFEnd"], + ["\r\n \r\ntest@iana.org", "errFWSCRLFEnd"], + [" \r\ntest@iana.org", "errFWSCRLFEnd"], + [" \r\n test@iana.org", "cfwsFWS"], + [" \r\n \r\ntest@iana.org", "errFWSCRLFEnd"], + [" \r\n\r\ntest@iana.org", "errFWSCRLFx2"], + [" \r\n\r\n test@iana.org", "errFWSCRLFx2"], + ["test@iana.org\r\n ", "cfwsFWS"], + ["test@iana.org\r\n \r\n ", "deprecatedFWS"], + ["test@iana.org\r\n", "errFWSCRLFEnd"], + ["test@iana.org \r", "errCRNoLF"], + ["test@iana.org\r\n \r\n", "errFWSCRLFEnd"], + ["test@iana.org \r\n", "errFWSCRLFEnd"], + ["test@iana.org \r\n ", "cfwsFWS"], + ["test@iana.org \r\n \r\n", "errFWSCRLFEnd"], + ["test@iana.org \r\n\r\n", "errFWSCRLFx2"], + ["test@iana.org \r\n\r\n ", "errFWSCRLFx2"], + ["test@iana. org", "deprecatedFWS"], + ["test@[\r", "errCRNoLF"], + ["test@[\r\n", "errFWSCRLFEnd"], + [" test@iana.org", "cfwsFWS"], + ["test@iana.org ", "cfwsFWS"], + ["test@[IPv6:1::2:]", "rfc5322IPv6ColonEnd"], + ["\"test\\©\"@iana.org", "errExpectingQPair"], + ["test@iana/icann.org", "rfc5322Domain"], + ["test@iana!icann.org", "rfc5322Domain"], + ["test@iana?icann.org", "rfc5322Domain"], + ["test@iana^icann.org", "rfc5322Domain"], + ["test@iana{icann}.org", "rfc5322Domain"], + ["test.(comment)test@iana.org", "deprecatedComment"], + ["test@iana.(comment)org", "deprecatedComment"], + ["test@iana(comment)iana.org", "errATEXTAfterCFWS"], + ["(comment\r\n comment)test@iana.org", "cfwsFWS"], + ["test@org", "rfc5321TLD"], + ["test@example.com", "dnsWarnNoMXRecord"], + ["test@nic.no", "dnsWarnNoRecord"] +]
@@ -0,0 +1,2 @@
+test +min/tests.js
@@ -0,0 +1,563 @@
+Changelog +========= + +### 2.14.1 +* [#3280](https://github.com/moment/moment/pull/3280) Fix typescript definitions + + +### 2.14.0 [See full changelog](https://gist.github.com/ichernev/812e79ac36a7829a22598fe964bfc18a) + +## New Features +* [#3233](http://github.com/moment/moment/pull/3233) Introduce month.isFormat for format/standalone discovery +* [#2848](http://github.com/moment/moment/pull/2848) Allow user to get/set the rounding method used when calculating relative time +* [#3112](http://github.com/moment/moment/pull/3112) optimize configFromStringAndFormat +* [#3147](http://github.com/moment/moment/pull/3147) Call calendar format function with moment context +* [#3160](http://github.com/moment/moment/pull/3160) deprecate isDSTShifted +* [#3175](http://github.com/moment/moment/pull/3175) make moment calendar extensible with ad-hoc options +* [#3191](http://github.com/moment/moment/pull/3191) toDate returns a copy of the internal date object +* [#3192](http://github.com/moment/moment/pull/3192) Adding support for rollup import. +* [#3238](http://github.com/moment/moment/pull/3238) Handle empty object and empty array for creation as now +* [#3082](http://github.com/moment/moment/pull/3082) Use relative AMD moment dependency + +## Bugfixes +* [#3241](http://github.com/moment/moment/pull/3241) Escape all 24 mixed pieces, not only first 12 in computeMonthsParse +* [#3008](http://github.com/moment/moment/pull/3008) Object setter orders sets based on size of unit +* [#3177](http://github.com/moment/moment/pull/3177) Bug Fix [#2704](http://github.com/moment/moment/pull/2704) - isoWeekday(String) inconsistent with isoWeekday(Number) +* [#3230](http://github.com/moment/moment/pull/3230) fix passing date with format string to ignore format string +* [#3232](http://github.com/moment/moment/pull/3232) Fix negative 0 in certain diff cases +* [#3235](http://github.com/moment/moment/pull/3235) Use proper locale inheritance for the base locale, fixes [#3137](http://github.com/moment/moment/pull/3137) + +Plus es-do locale and locale bugfixes + +### 2.13.0 [See full changelog](https://gist.github.com/ichernev/0132fcf5b61f7fc140b0bb0090480d49) + +## Enhancements: +* [#2982](https://github.com/moment/moment/pull/2982) Add 'date' as alias to 'day' for startOf() and endOf(). +* [#2955](https://github.com/moment/moment/pull/2955) Add parsing negative components in durations when ISO 8601 +* [#2991](https://github.com/moment/moment/pull/2991) isBetween support for both open and closed intervals +* [#3105](https://github.com/moment/moment/pull/3105) Add localeSorted argument to weekday listers +* [#3102](https://github.com/moment/moment/pull/3102) Add k and kk formatting tokens + +## Bugfixes +* [#3109](https://github.com/moment/moment/pull/3109) Fix [#1756](https://github.com/moment/moment/issues/1756) Resolved thread-safe issue on server side. +* [#3078](https://github.com/moment/moment/pull/3078) Fix parsing for months/weekdays with weird characters +* [#3098](https://github.com/moment/moment/pull/3098) Use Z suffix when in UTC mode ([#3020](https://github.com/moment/moment/issues/3020)) +* [#2995](https://github.com/moment/moment/pull/2995) Fix floating point rounding errors in durations +* [#3059](https://github.com/moment/moment/pull/3059) fix bug where diff returns -0 in month-related diffs +* [#3045](https://github.com/moment/moment/pull/3045) Fix mistaking any input for 'a' token +* [#2877](https://github.com/moment/moment/pull/2877) Use explicit .valueOf() calls instead of coercion +* [#3036](https://github.com/moment/moment/pull/3036) Year setter should keep time when DST changes + +Plus 3 new locales and locale fixes. + +### 2.12.0 [See full changelog](https://gist.github.com/ichernev/6e5bfdf8d6522fc4ac73) + +## Enhancements: +* [#2932](https://github.com/moment/moment/pull/2932) List loaded locales +* [#2818](https://github.com/moment/moment/pull/2818) Parse ISO-8061 duration containing both day and week values +* [#2774](https://github.com/moment/moment/pull/2774) Implement locale inheritance and locale updating + +## Bugfixes: +* [#2970](https://github.com/moment/moment/pull/2970) change add subtract to handle decimal values by rounding +* [#2887](https://github.com/moment/moment/pull/2887) Fix toJSON casting of invalid moment +* [#2897](https://github.com/moment/moment/pull/2897) parse string arguments for month() correctly, closes #2884 +* [#2946](https://github.com/moment/moment/pull/2946) Fix usage suggestions for min and max + +## New locales: +* [#2917](https://github.com/moment/moment/pull/2917) Locale Punjabi(Gurmukhi) India format conversion + +And more + +### 2.11.2 (Fix ReDoS attack vector) + +* [#2939](https://github.com/moment/moment/pull/2939) use full-string match to speed up aspnet regex match + +### 2.11.1 [See full changelog](https://gist.github.com/ichernev/8ec3ee25b749b4cff3c2) + +## Bugfixes: +* [#2881](https://github.com/moment/moment/pull/2881) Revert "Merge pull request #2746 from mbad0la:develop" Sep->Sept +* [#2868](https://github.com/moment/moment/pull/2868) Add format and parse token Y, so it actually works +* [#2865](https://github.com/moment/moment/pull/2865) Use typeof checks for undefined for global variables +* [#2858](https://github.com/moment/moment/pull/2858) Fix Date mocking regression introduced in 2.11.0 +* [#2864](https://github.com/moment/moment/pull/2864) Include changelog in npm release +* [#2830](https://github.com/moment/moment/pull/2830) dep: add grunt-cli +* [#2869](https://github.com/moment/moment/pull/2869) Fix months parsing for some locales + +### 2.11.0 [See full changelog](https://gist.github.com/ichernev/6594bc29719dde6b2f66) + +* [#2624](https://github.com/moment/moment/pull/2624) Proper handling of invalid moments +* [#2634](https://github.com/moment/moment/pull/2634) Fix strict month parsing issue in cs,ru,sk +* [#2735](https://github.com/moment/moment/pull/2735) Reset the locale back to 'en' after defining all locales in min/locales.js +* [#2702](https://github.com/moment/moment/pull/2702) Week rework +* [#2746](https://github.com/moment/moment/pull/2746) Changed September Abbreviation to "Sept" in locale-specific english + files and default locale file +* [#2646](https://github.com/moment/moment/pull/2646) Fix [#2645](https://github.com/moment/moment/pull/2645) - invalid dates pre-1970 + +* [#2641](https://github.com/moment/moment/pull/2641) Implement basic format and comma as ms separator in ISO 8601 +* [#2665](https://github.com/moment/moment/pull/2665) Implement stricter weekday parsing +* [#2700](https://github.com/moment/moment/pull/2700) Add [Hh]mm and [Hh]mmss formatting tokens, so you can parse 123 with + hmm for example +* [#2565](https://github.com/moment/moment/pull/2565) [#2835](https://github.com/moment/moment/pull/2835) Expose arguments used for moment creation with creationData + (fix [#2443](https://github.com/moment/moment/pull/2443)) +* [#2648](https://github.com/moment/moment/pull/2648) fix issue [#2640](https://github.com/moment/moment/pull/2640): support instanceof operator +* [#2709](https://github.com/moment/moment/pull/2709) Add isSameOrAfter and isSameOrBefore comparison methods +* [#2721](https://github.com/moment/moment/pull/2721) Fix moment creation from object with strings values +* [#2740](https://github.com/moment/moment/pull/2740) Enable 'd hh:mm:ss.sss' format for durations +* [#2766](https://github.com/moment/moment/pull/2766) [#2833](https://github.com/moment/moment/pull/2833) Alternate Clock Source Support + +### 2.10.6 + +[#2515](https://github.com/moment/moment/pull/2515) Fix regression introduced +in `2.10.5` related to `moment.ISO_8601` parsing. + +### 2.10.5 [See full changelog](https://gist.github.com/ichernev/6ec13ac7efc396da44b2) + +Important changes: +* [#2357](https://github.com/moment/moment/pull/2357) Improve unit bubbling for ISO dates + this fixes day to year conversions to work around end-of-year (~365 days). As + a side effect 365 days is 11 months and 30 days, and 366 days is one year. +* [#2438](https://github.com/moment/moment/pull/2438) Fix inconsistent moment.min and moment.max results + Return invalid result if any of the inputs is invalid +* [#2494](https://github.com/moment/moment/pull/2494) Fix two digit year parsing with YYYY format + This brings the benefits of YY to YYYY +* [#2368](https://github.com/moment/moment/pull/2368) perf: use faster form of copying dates, across the board improvement + + +### 2.10.3 [See full changelog](https://gist.github.com/ichernev/f264b9bed5b00f8b1b7f) + +* add `moment.fn.to` and `moment.fn.toNow` (similar to `from` and `fromNow`) +* new locales (Sinhalese (si), Montenegrin (me), Javanese (ja)) +* performance improvements + +### 2.10.2 + +* fixed moment-with-locales in browser env caused by esperanto change + +### 2.10.1 + +* regression: Add moment.duration.fn back + +### 2.10.0 + +Ported code to es6 modules. + +### 2.9.0 [See full changelog](https://gist.github.com/ichernev/0c9a9b49951111a27ce7) + +languages: +* [2104](https://github.com/moment/moment/issues/2104) Frisian (fy) language file with unit test +* [2097](https://github.com/moment/moment/issues/2097) add ar-tn locale + +deprecations: +* [2074](https://github.com/moment/moment/issues/2074) Implement `moment.fn.utcOffset`, deprecate `moment.fn.zone` + +features: +* [2088](https://github.com/moment/moment/issues/2088) add moment.fn.isBetween +* [2054](https://github.com/moment/moment/issues/2054) Call updateOffset when creating moment (needed for default timezone in + moment-timezone) +* [1893](https://github.com/moment/moment/issues/1893) Add moment.isDate method +* [1825](https://github.com/moment/moment/issues/1825) Implement toJSON function on Duration +* [1809](https://github.com/moment/moment/issues/1809) Allowing moment.set() to accept a hash of units +* [2128](https://github.com/moment/moment/issues/2128) Add firstDayOfWeek, firstDayOfYear locale getters +* [2131](https://github.com/moment/moment/issues/2131) Add quarter diff support + +Some bugfixes and language improvements -- [full changelog](https://gist.github.com/ichernev/0c9a9b49951111a27ce7) + +### 2.8.4 [See full changelog](https://gist.github.com/ichernev/a4fcb0a46d74e4b9b996) + +Features: + +* [#2000](https://github.com/moment/moment/issues/2000) Add LTS localised format that includes seconds +* [#1960](https://github.com/moment/moment/issues/1960) added formatToken 'x' for unix offset in milliseconds #1938 +* [#1965](https://github.com/moment/moment/issues/1965) Support 24:00:00.000 to mean next day, at midnight. +* [#2002](https://github.com/moment/moment/issues/2002) Accept 'date' key when creating moment with object +* [#2009](https://github.com/moment/moment/issues/2009) Use native toISOString when we can + +Some bugfixes and language improvements -- [full changelog](https://gist.github.com/ichernev/a4fcb0a46d74e4b9b996) + +### 2.8.3 + +Bugfixes: + +* [#1801](https://github.com/moment/moment/issues/1801) proper pluralization for Arabic +* [#1833](https://github.com/moment/moment/issues/1833) improve spm integration +* [#1871](https://github.com/moment/moment/issues/1871) fix zone bug caused by Firefox 24 +* [#1882](https://github.com/moment/moment/issues/1882) Use hh:mm in Czech +* [#1883](https://github.com/moment/moment/issues/1883) Fix 2.8.0 regression in duration as conversions +* [#1890](https://github.com/moment/moment/issues/1890) Faster travis builds +* [#1892](https://github.com/moment/moment/issues/1892) Faster isBefore/After/Same +* [#1848](https://github.com/moment/moment/issues/1848) Fix flaky month diffs +* [#1895](https://github.com/moment/moment/issues/1895) Fix 2.8.0 regression in moment.utc with format array +* [#1896](https://github.com/moment/moment/issues/1896) Support setting invalid instance locale (noop) +* [#1897](https://github.com/moment/moment/issues/1897) Support moment([str]) in addition to moment([int]) + +### 2.8.2 + +Minor bugfixes: + +* [#1874](https://github.com/moment/moment/issues/1874) use `Object.prototype.hasOwnProperty` + instead of `obj.hasOwnProperty` (ie8 bug) +* [#1873](https://github.com/moment/moment/issues/1873) add `duration#toString()` +* [#1859](https://github.com/moment/moment/issues/1859) better month/weekday names in norwegian +* [#1812](https://github.com/moment/moment/issues/1812) meridiem parsing for greek +* [#1804](https://github.com/moment/moment/issues/1804) spanish del -> de +* [#1800](https://github.com/moment/moment/issues/1800) korean LT improvement + +### 2.8.1 + +* bugfix [#1813](https://github.com/moment/moment/issues/1813): fix moment().lang([key]) incompatibility + +### 2.8.0 [See changelog](https://gist.github.com/ichernev/ac3899324a5fa6c8c9b4) + +* incompatible changes + * [#1761](https://github.com/moment/moment/issues/1761): moments created without a language are no longer following the global language, in case it changes. Only newly created moments take the global language by default. In case you're affected by this, wait, comment on [#1797](https://github.com/moment/moment/issues/1797) and wait for a proper reimplementation + * [#1642](https://github.com/moment/moment/issues/1642): 45 days is no longer "a month" according to humanize, cutoffs for month, and year have changed. Hopefully your code does not depend on a particular answer from humanize (which it shouldn't anyway) + * [#1784](https://github.com/moment/moment/issues/1784): if you use the human readable English datetime format in a weird way (like storing them in a database) that would break when the format changes you're at risk. + +* deprecations (old behavior will be dropped in 3.0) + * [#1761](https://github.com/moment/moment/issues/1761) `lang` is renamed to `locale`, `langData` -> `localeData`. Also there is now `defineLocale` that should be used when creating new locales + * [#1763](https://github.com/moment/moment/issues/1763) `add(unit, value)` and `subtract(unit, value)` are now deprecated. Use `add(value, unit)` and `subtract(value, unit)` instead. + * [#1759](https://github.com/moment/moment/issues/1759) rename `duration.toIsoString` to `duration.toISOString`. The js standard library and moment's `toISOString` follow that convention. + +* new locales + * [#1789](https://github.com/moment/moment/issues/1789) Tibetan (bo) + * [#1786](https://github.com/moment/moment/issues/1786) Africaans (af) + * [#1778](https://github.com/moment/moment/issues/1778) Burmese (my) + * [#1727](https://github.com/moment/moment/issues/1727) Belarusian (be) + +* bugfixes, locale bugfixes, performance improvements, features + +### 2.7.0 [See changelog](https://gist.github.com/ichernev/b0a3d456d5a84c9901d7) + +* new languages + + * [#1678](https://github.com/moment/moment/issues/1678) Bengali (bn) + * [#1628](https://github.com/moment/moment/issues/1628) Azerbaijani (az) + * [#1633](https://github.com/moment/moment/issues/1633) Arabic, Saudi Arabia (ar-sa) + * [#1648](https://github.com/moment/moment/issues/1648) Austrian German (de-at) + +* features + + * [#1663](https://github.com/moment/moment/issues/1663) configurable relative time thresholds + * [#1554](https://github.com/moment/moment/issues/1554) support anchor time in moment.calendar + * [#1693](https://github.com/moment/moment/issues/1693) support moment.ISO_8601 as parsing format + * [#1637](https://github.com/moment/moment/issues/1637) add moment.min and moment.max and deprecate min/max instance methods + * [#1704](https://github.com/moment/moment/issues/1704) support string value in add/subtract + * [#1647](https://github.com/moment/moment/issues/1647) add spm support (package manager) + +* bugfixes + +### 2.6.0 [See changelog](https://gist.github.com/ichernev/10544682) + +* languages + * [#1529](https://github.com/moment/moment/issues/1529) Serbian-Cyrillic (sr-cyr) + * [#1544](https://github.com/moment/moment/issues/1544), [#1546](https://github.com/moment/moment/issues/1546) Khmer Cambodia (km) + +* features + * [#1419](https://github.com/moment/moment/issues/1419), [#1468](https://github.com/moment/moment/issues/1468), [#1467](https://github.com/moment/moment/issues/1467), [#1546](https://github.com/moment/moment/issues/1546) better handling of timezone-d moments around DST + * [#1462](https://github.com/moment/moment/issues/1462) add weeksInYear and isoWeeksInYear + * [#1475](https://github.com/moment/moment/issues/1475) support ordinal parsing + * [#1499](https://github.com/moment/moment/issues/1499) composer support + * [#1577](https://github.com/moment/moment/issues/1577), [#1604](https://github.com/moment/moment/issues/1604) put Date parsing in moment.createFromInputFallback so it can be properly deprecated and controlled in the future + * [#1545](https://github.com/moment/moment/issues/1545) extract two-digit year parsing in moment.parseTwoDigitYear, so it can be overwritten + * [#1590](https://github.com/moment/moment/issues/1590) (see [#1574](https://github.com/moment/moment/issues/1574)) set AMD global before module definition to better support non AMD module dependencies used in AMD environment + * [#1589](https://github.com/moment/moment/issues/1589) remove global in Node.JS environment (was not working before, nobody complained, was scheduled for removal anyway) + * [#1586](https://github.com/moment/moment/issues/1586) support quarter setting and parsing + +* 18 bugs fixed + +### 2.5.1 + +* languages + * [#1392](https://github.com/moment/moment/issues/1392) Armenian (hy-am) + +* bugfixes + * [#1429](https://github.com/moment/moment/issues/1429) fixes [#1423](https://github.com/moment/moment/issues/1423) weird chrome-32 bug with js object creation + * [#1421](https://github.com/moment/moment/issues/1421) remove html entities from Welsh + * [#1418](https://github.com/moment/moment/issues/1418) fixes [#1401](https://github.com/moment/moment/issues/1401) improved non-padded tokens in strict matching + * [#1417](https://github.com/moment/moment/issues/1417) fixes [#1404](https://github.com/moment/moment/issues/1404) handle buggy moment object created by property cloning + * [#1398](https://github.com/moment/moment/issues/1398) fixes [#1397](https://github.com/moment/moment/issues/1397) fix Arabic-like week number parsing + * [#1396](https://github.com/moment/moment/issues/1396) add leftZeroFill(4) to GGGG and gggg formats + * [#1373](https://github.com/moment/moment/issues/1373) use lowercase for months and days in Catalan + +* testing + * [#1374](https://github.com/moment/moment/issues/1374) run tests on multiple browser/os combos via SauceLabs and Travis + +### 2.5.0 [See changelog](https://gist.github.com/ichernev/8104451) + +* New languages + * Luxemburish (lb) [1247](https://github.com/moment/moment/issues/1247) + * Serbian (rs) [1319](https://github.com/moment/moment/issues/1319) + * Tamil (ta) [1324](https://github.com/moment/moment/issues/1324) + * Macedonian (mk) [1337](https://github.com/moment/moment/issues/1337) + +* Features + * [1311](https://github.com/moment/moment/issues/1311) Add quarter getter and format token `Q` + * [1303](https://github.com/moment/moment/issues/1303) strict parsing now respects number of digits per token (fix [1196](https://github.com/moment/moment/issues/1196)) + * 0d30bb7 add jspm support + * [1347](https://github.com/moment/moment/issues/1347) improve zone parsing + * [1362](https://github.com/moment/moment/issues/1362) support merideam parsing in Korean + +* 22 bugfixes + +### 2.4.0 + +* **Deprecate** globally exported moment, will be removed in next major +* New languages + * Farose (fo) [#1206](https://github.com/moment/moment/issues/1206) + * Tagalog/Filipino (tl-ph) [#1197](https://github.com/moment/moment/issues/1197) + * Welsh (cy) [#1215](https://github.com/moment/moment/issues/1215) +* Bugfixes + * properly handle Z at the end of iso RegExp [#1187](https://github.com/moment/moment/issues/1187) + * chinese meridian time improvements [#1076](https://github.com/moment/moment/issues/1076) + * fix language tests [#1177](https://github.com/moment/moment/issues/1177) + * remove some failing tests (that should have never existed :)) + [#1185](https://github.com/moment/moment/issues/1185) + [#1183](https://github.com/moment/moment/issues/1183) + * handle russian noun cases in weird cases [#1195](https://github.com/moment/moment/issues/1195) + +### 2.3.1 + +Removed a trailing comma [1169] and fixed a bug with `months`, `weekdays` getters [#1171](https://github.com/moment/moment/issues/1171). + +### 2.3.0 [See changelog](https://gist.github.com/ichernev/6864354) + +Changed isValid, added strict parsing. +Week tokens parsing. + +### 2.2.1 + +Fixed bug in string prototype test. +Updated authors and contributors. + +### 2.2.0 [See changelog](https://gist.github.com/ichernev/00f837a9baf46a3565e4) + +Added bower support. + +Language files now use UMD. + +Creating moment defaults to current date/month/year. + +Added a bundle of moment and all language files. + +### 2.1.0 [See changelog](https://gist.github.com/timrwood/b8c2d90d528eddb53ab5) + +Added better week support. + +Added ability to set offset with `moment#zone`. + +Added ability to set month or weekday from a string. + +Added `moment#min` and `moment#max` + +### 2.0.0 [See changelog](https://gist.github.com/timrwood/e72f2eef320ed9e37c51) + +Added short form localized tokens. + +Added ability to define language a string should be parsed in. + +Added support for reversed add/subtract arguments. + +Added support for `endOf('week')` and `startOf('week')`. + +Fixed the logic for `moment#diff(Moment, 'months')` and `moment#diff(Moment, 'years')` + +`moment#diff` now floors instead of rounds. + +Normalized `moment#toString`. + +Added `isSame`, `isAfter`, and `isBefore` methods. + +Added better week support. + +Added `moment#toJSON` + +Bugfix: Fixed parsing of first century dates + +Bugfix: Parsing 10Sep2001 should work as expected + +Bugfix: Fixed weirdness with `moment.utc()` parsing. + +Changed language ordinal method to return the number + ordinal instead of just the ordinal. + +Changed two digit year parsing cutoff to match strptime. + +Removed `moment#sod` and `moment#eod` in favor of `moment#startOf` and `moment#endOf`. + +Removed `moment.humanizeDuration()` in favor of `moment.duration().humanize()`. + +Removed the lang data objects from the top level namespace. + +Duplicate `Date` passed to `moment()` instead of referencing it. + +### 1.7.2 [See discussion](https://github.com/timrwood/moment/issues/456) + +Bugfixes + +### 1.7.1 [See discussion](https://github.com/timrwood/moment/issues/384) + +Bugfixes + +### 1.7.0 [See discussion](https://github.com/timrwood/moment/issues/288) + +Added `moment.fn.endOf()` and `moment.fn.startOf()`. + +Added validation via `moment.fn.isValid()`. + +Made formatting method 3x faster. http://jsperf.com/momentjs-cached-format-functions + +Add support for month/weekday callbacks in `moment.fn.format()` + +Added instance specific languages. + +Added two letter weekday abbreviations with the formatting token `dd`. + +Various language updates. + +Various bugfixes. + +### 1.6.0 [See discussion](https://github.com/timrwood/moment/pull/268) + +Added Durations. + +Revamped parser to support parsing non-separated strings (YYYYMMDD vs YYYY-MM-DD). + +Added support for millisecond parsing and formatting tokens (S SS SSS) + +Added a getter for `moment.lang()` + +Various bugfixes. + +There are a few things deprecated in the 1.6.0 release. + +1. The format tokens `z` and `zz` (timezone abbreviations like EST CST MST etc) will no longer be supported. Due to inconsistent browser support, we are unable to consistently produce this value. See [this issue](https://github.com/timrwood/moment/issues/162) for more background. + +2. The method `moment.fn.native` is deprecated in favor of `moment.fn.toDate`. There continue to be issues with Google Closure Compiler throwing errors when using `native`, even in valid instances. + +3. The way to customize am/pm strings is being changed. This would only affect you if you created a custom language file. For more information, see [this issue](https://github.com/timrwood/moment/pull/222). + +### 1.5.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=10&page=1&state=closed) + +Added UTC mode. + +Added automatic ISO8601 parsing. + +Various bugfixes. + +### 1.4.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=8&state=closed) + +Added `moment.fn.toDate` as a replacement for `moment.fn.native`. + +Added `moment.fn.sod` and `moment.fn.eod` to get the start and end of day. + +Various bugfixes. + +### 1.3.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=7&state=closed) + +Added support for parsing month names in the current language. + +Added escape blocks for parsing tokens. + +Added `moment.fn.calendar` to format strings like 'Today 2:30 PM', 'Tomorrow 1:25 AM', and 'Last Sunday 4:30 AM'. + +Added `moment.fn.day` as a setter. + +Various bugfixes + +### 1.2.0 [See milestone](https://github.com/timrwood/moment/issues?milestone=4&state=closed) + +Added timezones to parser and formatter. + +Added `moment.fn.isDST`. + +Added `moment.fn.zone` to get the timezone offset in minutes. + +### 1.1.2 [See milestone](https://github.com/timrwood/moment/issues?milestone=6&state=closed) + +Various bugfixes + +### 1.1.1 [See milestone](https://github.com/timrwood/moment/issues?milestone=5&state=closed) + +Added time specific diffs (months, days, hours, etc) + +### 1.1.0 + +Added `moment.fn.format` localized masks. 'L LL LLL LLLL' [issue 29](https://github.com/timrwood/moment/pull/29) + +Fixed [issue 31](https://github.com/timrwood/moment/pull/31). + +### 1.0.1 + +Added `moment.version` to get the current version. + +Removed `window !== undefined` when checking if module exists to support browserify. [issue 25](https://github.com/timrwood/moment/pull/25) + +### 1.0.0 + +Added convenience methods for getting and setting date parts. + +Added better support for `moment.add()`. + +Added better lang support in NodeJS. + +Renamed library from underscore.date to Moment.js + +### 0.6.1 + +Added Portuguese, Italian, and French language support + +### 0.6.0 + +Added _date.lang() support. +Added support for passing multiple formats to try to parse a date. _date("07-10-1986", ["MM-DD-YYYY", "YYYY-MM-DD"]); +Made parse from string and single format 25% faster. + +### 0.5.2 + +Bugfix for [issue 8](https://github.com/timrwood/underscore.date/pull/8) and [issue 9](https://github.com/timrwood/underscore.date/pull/9). + +### 0.5.1 + +Bugfix for [issue 5](https://github.com/timrwood/underscore.date/pull/5). + +### 0.5.0 + +Dropped the redundant `_date.date()` in favor of `_date()`. +Removed `_date.now()`, as it is a duplicate of `_date()` with no parameters. +Removed `_date.isLeapYear(yearNumber)`. Use `_date([yearNumber]).isLeapYear()` instead. +Exposed customization options through the `_date.relativeTime`, `_date.weekdays`, `_date.weekdaysShort`, `_date.months`, `_date.monthsShort`, and `_date.ordinal` variables instead of the `_date.customize()` function. + +### 0.4.1 + +Added date input formats for input strings. + +### 0.4.0 + +Added underscore.date to npm. Removed dependencies on underscore. + +### 0.3.2 + +Added `'z'` and `'zz'` to `_.date().format()`. Cleaned up some redundant code to trim off some bytes. + +### 0.3.1 + +Cleaned up the namespace. Moved all date manipulation and display functions to the _.date() object. + +### 0.3.0 + +Switched to the Underscore methodology of not mucking with the native objects' prototypes. +Made chaining possible. + +### 0.2.1 + +Changed date names to be a more pseudo standardized 'dddd, MMMM Do YYYY, h:mm:ss a'. +Added `Date.prototype` functions `add`, `subtract`, `isdst`, and `isleapyear`. + +### 0.2.0 + +Changed function names to be more concise. +Changed date format from php date format to custom format. + +### 0.1.0 + +Initial release +
@@ -0,0 +1,22 @@
+Copyright (c) 2011-2016 Tim Wood, Iskren Chernev, Moment.js contributors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,58 @@
+[](https://gitter.im/moment/moment?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +[![NPM version][npm-version-image]][npm-url] [![NPM downloads][npm-downloads-image]][npm-url] [![MIT License][license-image]][license-url] [![Build Status][travis-image]][travis-url] +[](https://coveralls.io/r/moment/moment?branch=develop) + +A lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates. + +**[Documentation](http://momentjs.com/docs/)** + +## Port to ECMAScript 6 (version 2.10.0) + +Moment 2.10.0 does not bring any new features, but the code is now written in +ECMAScript 6 modules and placed inside `src/`. Previously `moment.js`, `locale/*.js` and +`test/moment/*.js`, `test/locale/*.js` contained the source of the project. Now +the source is in `src/`, temporary build (ECMAScript 5) files are placed under +`build/umd/` (for running tests during development), and the `moment.js` and +`locale/*.js` files are updated only on release. + +If you want to use a particular revision of the code, make sure to run +`grunt transpile update-index`, so `moment.js` and `locales/*.js` are synced +with `src/*`. We might place that in a commit hook in the future. + +## Upgrading to 2.0.0 + +There are a number of small backwards incompatible changes with version 2.0.0. [See the full descriptions here](https://gist.github.com/timrwood/e72f2eef320ed9e37c51#backwards-incompatible-changes) + + * Changed language ordinal method to return the number + ordinal instead of just the ordinal. + + * Changed two digit year parsing cutoff to match strptime. + + * Removed `moment#sod` and `moment#eod` in favor of `moment#startOf` and `moment#endOf`. + + * Removed `moment.humanizeDuration()` in favor of `moment.duration().humanize()`. + + * Removed the lang data objects from the top level namespace. + + * Duplicate `Date` passed to `moment()` instead of referencing it. + +## [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md) + +## [Contributing](https://github.com/moment/moment/blob/develop/CONTRIBUTING.md) + +We're looking for co-maintainers! If you want to become a master of time please +write to [ichernev](https://github.com/ichernev). + +## License + +Moment.js is freely distributable under the terms of the [MIT license](https://github.com/moment/moment/blob/develop/LICENSE). + +[license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat +[license-url]: LICENSE + +[npm-url]: https://npmjs.org/package/moment +[npm-version-image]: http://img.shields.io/npm/v/moment.svg?style=flat +[npm-downloads-image]: http://img.shields.io/npm/dm/moment.svg?style=flat + +[travis-url]: http://travis-ci.org/moment/moment +[travis-image]: http://img.shields.io/travis/moment/moment/develop.svg?style=flat
@@ -0,0 +1,1 @@
+$.ender({ moment: require('moment') })
@@ -0,0 +1,73 @@
+//! moment.js locale configuration +//! locale : Afrikaans [af] +//! author : Werner Mollentze : https://github.com/wernerm + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var af = moment.defineLocale('af', { + months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'), + weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'), + weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'), + meridiemParse: /vm|nm/i, + isPM : function (input) { + return /^nm$/i.test(input); + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower ? 'vm' : 'VM'; + } else { + return isLower ? 'nm' : 'NM'; + } + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Vandag om] LT', + nextDay : '[Môre om] LT', + nextWeek : 'dddd [om] LT', + lastDay : '[Gister om] LT', + lastWeek : '[Laas] dddd [om] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'oor %s', + past : '%s gelede', + s : '\'n paar sekondes', + m : '\'n minuut', + mm : '%d minute', + h : '\'n uur', + hh : '%d ure', + d : '\'n dag', + dd : '%d dae', + M : '\'n maand', + MM : '%d maande', + y : '\'n jaar', + yy : '%d jaar' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter + }, + week : { + dow : 1, // Maandag is die eerste dag van die week. + doy : 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar. + } + }); + + return af; + +}));
@@ -0,0 +1,60 @@
+//! moment.js locale configuration +//! locale : Arabic (Morocco) [ar-ma] +//! author : ElFadili Yassine : https://github.com/ElFadiliY +//! author : Abdel Said : https://github.com/abdelsaid + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ar_ma = moment.defineLocale('ar-ma', { + months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[اليوم على الساعة] LT', + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'في %s', + past : 'منذ %s', + s : 'ثوان', + m : 'دقيقة', + mm : '%d دقائق', + h : 'ساعة', + hh : '%d ساعات', + d : 'يوم', + dd : '%d أيام', + M : 'شهر', + MM : '%d أشهر', + y : 'سنة', + yy : '%d سنوات' + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + return ar_ma; + +}));
@@ -0,0 +1,104 @@
+//! moment.js locale configuration +//! locale : Arabic (Saudi Arabia) [ar-sa] +//! author : Suhail Alkowaileet : https://github.com/xsoh + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' + }, numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' + }; + + var ar_sa = moment.defineLocale('ar-sa', { + months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ص'; + } else { + return 'م'; + } + }, + calendar : { + sameDay: '[اليوم على الساعة] LT', + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'في %s', + past : 'منذ %s', + s : 'ثوان', + m : 'دقيقة', + mm : '%d دقائق', + h : 'ساعة', + hh : '%d ساعات', + d : 'يوم', + dd : '%d أيام', + M : 'شهر', + MM : '%d أشهر', + y : 'سنة', + yy : '%d سنوات' + }, + preparse: function (string) { + return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) { + return numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }).replace(/,/g, '،'); + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + return ar_sa; + +}));
@@ -0,0 +1,58 @@
+//! moment.js locale configuration +//! locale : Arabic (Tunisia) [ar-tn] + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ar_tn = moment.defineLocale('ar-tn', { + months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[اليوم على الساعة] LT', + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime: { + future: 'في %s', + past: 'منذ %s', + s: 'ثوان', + m: 'دقيقة', + mm: '%d دقائق', + h: 'ساعة', + hh: '%d ساعات', + d: 'يوم', + dd: '%d أيام', + M: 'شهر', + MM: '%d أشهر', + y: 'سنة', + yy: '%d سنوات' + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return ar_tn; + +}));
@@ -0,0 +1,137 @@
+//! moment.js locale configuration +//! locale : Arabic [ar] +//! author : Abdel Said: https://github.com/abdelsaid +//! changes in months, weekdays: Ahmed Elkhatib +//! Native plural forms: forabi https://github.com/forabi + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' + }, numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' + }, pluralForm = function (n) { + return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5; + }, plurals = { + s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'], + m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'], + h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'], + d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'], + M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'], + y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام'] + }, pluralize = function (u) { + return function (number, withoutSuffix, string, isFuture) { + var f = pluralForm(number), + str = plurals[u][pluralForm(number)]; + if (f === 2) { + str = str[withoutSuffix ? 0 : 1]; + } + return str.replace(/%d/i, number); + }; + }, months = [ + 'كانون الثاني يناير', + 'شباط فبراير', + 'آذار مارس', + 'نيسان أبريل', + 'أيار مايو', + 'حزيران يونيو', + 'تموز يوليو', + 'آب أغسطس', + 'أيلول سبتمبر', + 'تشرين الأول أكتوبر', + 'تشرين الثاني نوفمبر', + 'كانون الأول ديسمبر' + ]; + + var ar = moment.defineLocale('ar', { + months : months, + monthsShort : months, + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'D/\u200FM/\u200FYYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ص'; + } else { + return 'م'; + } + }, + calendar : { + sameDay: '[اليوم عند الساعة] LT', + nextDay: '[غدًا عند الساعة] LT', + nextWeek: 'dddd [عند الساعة] LT', + lastDay: '[أمس عند الساعة] LT', + lastWeek: 'dddd [عند الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'بعد %s', + past : 'منذ %s', + s : pluralize('s'), + m : pluralize('m'), + mm : pluralize('m'), + h : pluralize('h'), + hh : pluralize('h'), + d : pluralize('d'), + dd : pluralize('d'), + M : pluralize('M'), + MM : pluralize('M'), + y : pluralize('y'), + yy : pluralize('y') + }, + preparse: function (string) { + return string.replace(/\u200f/g, '').replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) { + return numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }).replace(/,/g, '،'); + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + return ar; + +}));
@@ -0,0 +1,105 @@
+//! moment.js locale configuration +//! locale : Azerbaijani [az] +//! author : topchiyev : https://github.com/topchiyev + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var suffixes = { + 1: '-inci', + 5: '-inci', + 8: '-inci', + 70: '-inci', + 80: '-inci', + 2: '-nci', + 7: '-nci', + 20: '-nci', + 50: '-nci', + 3: '-üncü', + 4: '-üncü', + 100: '-üncü', + 6: '-ncı', + 9: '-uncu', + 10: '-uncu', + 30: '-uncu', + 60: '-ıncı', + 90: '-ıncı' + }; + + var az = moment.defineLocale('az', { + months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'), + monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'), + weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'), + weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'), + weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[bugün saat] LT', + nextDay : '[sabah saat] LT', + nextWeek : '[gələn həftə] dddd [saat] LT', + lastDay : '[dünən] LT', + lastWeek : '[keçən həftə] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s sonra', + past : '%s əvvəl', + s : 'birneçə saniyyə', + m : 'bir dəqiqə', + mm : '%d dəqiqə', + h : 'bir saat', + hh : '%d saat', + d : 'bir gün', + dd : '%d gün', + M : 'bir ay', + MM : '%d ay', + y : 'bir il', + yy : '%d il' + }, + meridiemParse: /gecə|səhər|gündüz|axşam/, + isPM : function (input) { + return /^(gündüz|axşam)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'gecə'; + } else if (hour < 12) { + return 'səhər'; + } else if (hour < 17) { + return 'gündüz'; + } else { + return 'axşam'; + } + }, + ordinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/, + ordinal : function (number) { + if (number === 0) { // special case for zero + return number + '-ıncı'; + } + var a = number % 10, + b = number % 100 - a, + c = number >= 100 ? 100 : null; + return number + (suffixes[a] || suffixes[b] || suffixes[c]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return az; + +}));
@@ -0,0 +1,134 @@
+//! moment.js locale configuration +//! locale : Belarusian [be] +//! author : Dmitry Demidov : https://github.com/demidov91 +//! author: Praleska: http://praleska.pro/ +//! Author : Menelion Elensúle : https://github.com/Oire + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); + } + function relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін', + 'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін', + 'dd': 'дзень_дні_дзён', + 'MM': 'месяц_месяцы_месяцаў', + 'yy': 'год_гады_гадоў' + }; + if (key === 'm') { + return withoutSuffix ? 'хвіліна' : 'хвіліну'; + } + else if (key === 'h') { + return withoutSuffix ? 'гадзіна' : 'гадзіну'; + } + else { + return number + ' ' + plural(format[key], +number); + } + } + + var be = moment.defineLocale('be', { + months : { + format: 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_'), + standalone: 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_') + }, + monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'), + weekdays : { + format: 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_'), + standalone: 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'), + isFormat: /\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/ + }, + weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY г.', + LLL : 'D MMMM YYYY г., HH:mm', + LLLL : 'dddd, D MMMM YYYY г., HH:mm' + }, + calendar : { + sameDay: '[Сёння ў] LT', + nextDay: '[Заўтра ў] LT', + lastDay: '[Учора ў] LT', + nextWeek: function () { + return '[У] dddd [ў] LT'; + }, + lastWeek: function () { + switch (this.day()) { + case 0: + case 3: + case 5: + case 6: + return '[У мінулую] dddd [ў] LT'; + case 1: + case 2: + case 4: + return '[У мінулы] dddd [ў] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'праз %s', + past : '%s таму', + s : 'некалькі секунд', + m : relativeTimeWithPlural, + mm : relativeTimeWithPlural, + h : relativeTimeWithPlural, + hh : relativeTimeWithPlural, + d : 'дзень', + dd : relativeTimeWithPlural, + M : 'месяц', + MM : relativeTimeWithPlural, + y : 'год', + yy : relativeTimeWithPlural + }, + meridiemParse: /ночы|раніцы|дня|вечара/, + isPM : function (input) { + return /^(дня|вечара)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночы'; + } else if (hour < 12) { + return 'раніцы'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечара'; + } + }, + ordinalParse: /\d{1,2}-(і|ы|га)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + case 'w': + case 'W': + return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : number + '-ы'; + case 'D': + return number + '-га'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return be; + +}));
@@ -0,0 +1,90 @@
+//! moment.js locale configuration +//! locale : Bulgarian [bg] +//! author : Krasen Borisov : https://github.com/kraz + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var bg = moment.defineLocale('bg', { + months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'), + weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'D.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd, D MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[Днес в] LT', + nextDay : '[Утре в] LT', + nextWeek : 'dddd [в] LT', + lastDay : '[Вчера в] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + case 6: + return '[В изминалата] dddd [в] LT'; + case 1: + case 2: + case 4: + case 5: + return '[В изминалия] dddd [в] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'след %s', + past : 'преди %s', + s : 'няколко секунди', + m : 'минута', + mm : '%d минути', + h : 'час', + hh : '%d часа', + d : 'ден', + dd : '%d дни', + M : 'месец', + MM : '%d месеца', + y : 'година', + yy : '%d години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + ordinal : function (number) { + var lastDigit = number % 10, + last2Digits = number % 100; + if (number === 0) { + return number + '-ев'; + } else if (last2Digits === 0) { + return number + '-ен'; + } else if (last2Digits > 10 && last2Digits < 20) { + return number + '-ти'; + } else if (lastDigit === 1) { + return number + '-ви'; + } else if (lastDigit === 2) { + return number + '-ри'; + } else if (lastDigit === 7 || lastDigit === 8) { + return number + '-ми'; + } else { + return number + '-ти'; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return bg; + +}));
@@ -0,0 +1,119 @@
+//! moment.js locale configuration +//! locale : Bengali [bn] +//! author : Kaushik Gandhi : https://github.com/kaushikgandhi + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '১', + '2': '২', + '3': '৩', + '4': '৪', + '5': '৫', + '6': '৬', + '7': '৭', + '8': '৮', + '9': '৯', + '0': '০' + }, + numberMap = { + '১': '1', + '২': '2', + '৩': '3', + '৪': '4', + '৫': '5', + '৬': '6', + '৭': '7', + '৮': '8', + '৯': '9', + '০': '0' + }; + + var bn = moment.defineLocale('bn', { + months : 'জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'), + monthsShort : 'জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্'.split('_'), + weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রবার_শনিবার'.split('_'), + weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্র_শনি'.split('_'), + weekdaysMin : 'রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি'.split('_'), + longDateFormat : { + LT : 'A h:mm সময়', + LTS : 'A h:mm:ss সময়', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm সময়', + LLLL : 'dddd, D MMMM YYYY, A h:mm সময়' + }, + calendar : { + sameDay : '[আজ] LT', + nextDay : '[আগামীকাল] LT', + nextWeek : 'dddd, LT', + lastDay : '[গতকাল] LT', + lastWeek : '[গত] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s পরে', + past : '%s আগে', + s : 'কয়েক সেকেন্ড', + m : 'এক মিনিট', + mm : '%d মিনিট', + h : 'এক ঘন্টা', + hh : '%d ঘন্টা', + d : 'এক দিন', + dd : '%d দিন', + M : 'এক মাস', + MM : '%d মাস', + y : 'এক বছর', + yy : '%d বছর' + }, + preparse: function (string) { + return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + meridiemParse: /রাত|সকাল|দুপুর|বিকাল|রাত/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if ((meridiem === 'রাত' && hour >= 4) || + (meridiem === 'দুপুর' && hour < 5) || + meridiem === 'বিকাল') { + return hour + 12; + } else { + return hour; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'রাত'; + } else if (hour < 10) { + return 'সকাল'; + } else if (hour < 17) { + return 'দুপুর'; + } else if (hour < 20) { + return 'বিকাল'; + } else { + return 'রাত'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + return bn; + +}));
@@ -0,0 +1,119 @@
+//! moment.js locale configuration +//! locale : Tibetan [bo] +//! author : Thupten N. Chakrishar : https://github.com/vajradog + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '༡', + '2': '༢', + '3': '༣', + '4': '༤', + '5': '༥', + '6': '༦', + '7': '༧', + '8': '༨', + '9': '༩', + '0': '༠' + }, + numberMap = { + '༡': '1', + '༢': '2', + '༣': '3', + '༤': '4', + '༥': '5', + '༦': '6', + '༧': '7', + '༨': '8', + '༩': '9', + '༠': '0' + }; + + var bo = moment.defineLocale('bo', { + months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'), + weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + longDateFormat : { + LT : 'A h:mm', + LTS : 'A h:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm', + LLLL : 'dddd, D MMMM YYYY, A h:mm' + }, + calendar : { + sameDay : '[དི་རིང] LT', + nextDay : '[སང་ཉིན] LT', + nextWeek : '[བདུན་ཕྲག་རྗེས་མ], LT', + lastDay : '[ཁ་སང] LT', + lastWeek : '[བདུན་ཕྲག་མཐའ་མ] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ལ་', + past : '%s སྔན་ལ', + s : 'ལམ་སང', + m : 'སྐར་མ་གཅིག', + mm : '%d སྐར་མ', + h : 'ཆུ་ཚོད་གཅིག', + hh : '%d ཆུ་ཚོད', + d : 'ཉིན་གཅིག', + dd : '%d ཉིན་', + M : 'ཟླ་བ་གཅིག', + MM : '%d ཟླ་བ', + y : 'ལོ་གཅིག', + yy : '%d ལོ' + }, + preparse: function (string) { + return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if ((meridiem === 'མཚན་མོ' && hour >= 4) || + (meridiem === 'ཉིན་གུང' && hour < 5) || + meridiem === 'དགོང་དག') { + return hour + 12; + } else { + return hour; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'མཚན་མོ'; + } else if (hour < 10) { + return 'ཞོགས་ཀས'; + } else if (hour < 17) { + return 'ཉིན་གུང'; + } else if (hour < 20) { + return 'དགོང་དག'; + } else { + return 'མཚན་མོ'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + return bo; + +}));
@@ -0,0 +1,108 @@
+//! moment.js locale configuration +//! locale : Breton [br] +//! author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function relativeTimeWithMutation(number, withoutSuffix, key) { + var format = { + 'mm': 'munutenn', + 'MM': 'miz', + 'dd': 'devezh' + }; + return number + ' ' + mutation(format[key], number); + } + function specialMutationForYears(number) { + switch (lastNumber(number)) { + case 1: + case 3: + case 4: + case 5: + case 9: + return number + ' bloaz'; + default: + return number + ' vloaz'; + } + } + function lastNumber(number) { + if (number > 9) { + return lastNumber(number % 10); + } + return number; + } + function mutation(text, number) { + if (number === 2) { + return softMutation(text); + } + return text; + } + function softMutation(text) { + var mutationTable = { + 'm': 'v', + 'b': 'v', + 'd': 'z' + }; + if (mutationTable[text.charAt(0)] === undefined) { + return text; + } + return mutationTable[text.charAt(0)] + text.substring(1); + } + + var br = moment.defineLocale('br', { + months : 'Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split('_'), + monthsShort : 'Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'), + weekdays : 'Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn'.split('_'), + weekdaysShort : 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'), + weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'h[e]mm A', + LTS : 'h[e]mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D [a viz] MMMM YYYY', + LLL : 'D [a viz] MMMM YYYY h[e]mm A', + LLLL : 'dddd, D [a viz] MMMM YYYY h[e]mm A' + }, + calendar : { + sameDay : '[Hiziv da] LT', + nextDay : '[Warc\'hoazh da] LT', + nextWeek : 'dddd [da] LT', + lastDay : '[Dec\'h da] LT', + lastWeek : 'dddd [paset da] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'a-benn %s', + past : '%s \'zo', + s : 'un nebeud segondennoù', + m : 'ur vunutenn', + mm : relativeTimeWithMutation, + h : 'un eur', + hh : '%d eur', + d : 'un devezh', + dd : relativeTimeWithMutation, + M : 'ur miz', + MM : relativeTimeWithMutation, + y : 'ur bloaz', + yy : specialMutationForYears + }, + ordinalParse: /\d{1,2}(añ|vet)/, + ordinal : function (number) { + var output = (number === 1) ? 'añ' : 'vet'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return br; + +}));
@@ -0,0 +1,143 @@
+//! moment.js locale configuration +//! locale : Bosnian [bs] +//! author : Nedim Cholich : https://github.com/frontyard +//! based on (hr) translation by Bojan Marković + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } + } + + var bs = moment.defineLocale('bs', { + months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : translate, + mm : translate, + h : translate, + hh : translate, + d : 'dan', + dd : translate, + M : 'mjesec', + MM : translate, + y : 'godinu', + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return bs; + +}));
@@ -0,0 +1,81 @@
+//! moment.js locale configuration +//! locale : Catalan [ca] +//! author : Juan G. Hurtado : https://github.com/juanghurtado + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ca = moment.defineLocale('ca', { + months : 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'), + monthsShort : 'gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.'.split('_'), + monthsParseExact : true, + weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'), + weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'), + weekdaysMin : 'Dg_Dl_Dt_Dc_Dj_Dv_Ds'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd D MMMM YYYY H:mm' + }, + calendar : { + sameDay : function () { + return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + nextDay : function () { + return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + lastDay : function () { + return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'en %s', + past : 'fa %s', + s : 'uns segons', + m : 'un minut', + mm : '%d minuts', + h : 'una hora', + hh : '%d hores', + d : 'un dia', + dd : '%d dies', + M : 'un mes', + MM : '%d mesos', + y : 'un any', + yy : '%d anys' + }, + ordinalParse: /\d{1,2}(r|n|t|è|a)/, + ordinal : function (number, period) { + var output = (number === 1) ? 'r' : + (number === 2) ? 'n' : + (number === 3) ? 'r' : + (number === 4) ? 't' : 'è'; + if (period === 'w' || period === 'W') { + output = 'a'; + } + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return ca; + +}));
@@ -0,0 +1,172 @@
+//! moment.js locale configuration +//! locale : Czech [cs] +//! author : petrbela : https://github.com/petrbela + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_'), + monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_'); + function plural(n) { + return (n > 1) && (n < 5) && (~~(n / 10) !== 1); + } + function translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': // a few seconds / in a few seconds / a few seconds ago + return (withoutSuffix || isFuture) ? 'pár sekund' : 'pár sekundami'; + case 'm': // a minute / in a minute / a minute ago + return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou'); + case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'minuty' : 'minut'); + } else { + return result + 'minutami'; + } + break; + case 'h': // an hour / in an hour / an hour ago + return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou'); + case 'hh': // 9 hours / in 9 hours / 9 hours ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'hodiny' : 'hodin'); + } else { + return result + 'hodinami'; + } + break; + case 'd': // a day / in a day / a day ago + return (withoutSuffix || isFuture) ? 'den' : 'dnem'; + case 'dd': // 9 days / in 9 days / 9 days ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'dny' : 'dní'); + } else { + return result + 'dny'; + } + break; + case 'M': // a month / in a month / a month ago + return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem'; + case 'MM': // 9 months / in 9 months / 9 months ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'měsíce' : 'měsíců'); + } else { + return result + 'měsíci'; + } + break; + case 'y': // a year / in a year / a year ago + return (withoutSuffix || isFuture) ? 'rok' : 'rokem'; + case 'yy': // 9 years / in 9 years / 9 years ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'roky' : 'let'); + } else { + return result + 'lety'; + } + break; + } + } + + var cs = moment.defineLocale('cs', { + months : months, + monthsShort : monthsShort, + monthsParse : (function (months, monthsShort) { + var i, _monthsParse = []; + for (i = 0; i < 12; i++) { + // use custom parser to solve problem with July (červenec) + _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i'); + } + return _monthsParse; + }(months, monthsShort)), + shortMonthsParse : (function (monthsShort) { + var i, _shortMonthsParse = []; + for (i = 0; i < 12; i++) { + _shortMonthsParse[i] = new RegExp('^' + monthsShort[i] + '$', 'i'); + } + return _shortMonthsParse; + }(monthsShort)), + longMonthsParse : (function (months) { + var i, _longMonthsParse = []; + for (i = 0; i < 12; i++) { + _longMonthsParse[i] = new RegExp('^' + months[i] + '$', 'i'); + } + return _longMonthsParse; + }(months)), + weekdays : 'neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota'.split('_'), + weekdaysShort : 'ne_po_út_st_čt_pá_so'.split('_'), + weekdaysMin : 'ne_po_út_st_čt_pá_so'.split('_'), + longDateFormat : { + LT: 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd D. MMMM YYYY H:mm', + l : 'D. M. YYYY' + }, + calendar : { + sameDay: '[dnes v] LT', + nextDay: '[zítra v] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[v neděli v] LT'; + case 1: + case 2: + return '[v] dddd [v] LT'; + case 3: + return '[ve středu v] LT'; + case 4: + return '[ve čtvrtek v] LT'; + case 5: + return '[v pátek v] LT'; + case 6: + return '[v sobotu v] LT'; + } + }, + lastDay: '[včera v] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[minulou neděli v] LT'; + case 1: + case 2: + return '[minulé] dddd [v] LT'; + case 3: + return '[minulou středu v] LT'; + case 4: + case 5: + return '[minulý] dddd [v] LT'; + case 6: + return '[minulou sobotu v] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'za %s', + past : 'před %s', + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinalParse : /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return cs; + +}));
@@ -0,0 +1,63 @@
+//! moment.js locale configuration +//! locale : Chuvash [cv] +//! author : Anatoly Mironov : https://github.com/mirontoli + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var cv = moment.defineLocale('cv', { + months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'), + monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'), + weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'), + weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'), + weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]', + LLL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm', + LLLL : 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm' + }, + calendar : { + sameDay: '[Паян] LT [сехетре]', + nextDay: '[Ыран] LT [сехетре]', + lastDay: '[Ӗнер] LT [сехетре]', + nextWeek: '[Ҫитес] dddd LT [сехетре]', + lastWeek: '[Иртнӗ] dddd LT [сехетре]', + sameElse: 'L' + }, + relativeTime : { + future : function (output) { + var affix = /сехет$/i.exec(output) ? 'рен' : /ҫул$/i.exec(output) ? 'тан' : 'ран'; + return output + affix; + }, + past : '%s каялла', + s : 'пӗр-ик ҫеккунт', + m : 'пӗр минут', + mm : '%d минут', + h : 'пӗр сехет', + hh : '%d сехет', + d : 'пӗр кун', + dd : '%d кун', + M : 'пӗр уйӑх', + MM : '%d уйӑх', + y : 'пӗр ҫул', + yy : '%d ҫул' + }, + ordinalParse: /\d{1,2}-мӗш/, + ordinal : '%d-мӗш', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return cv; + +}));
@@ -0,0 +1,80 @@
+//! moment.js locale configuration +//! locale : Welsh [cy] +//! author : Robert Allen + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var cy = moment.defineLocale('cy', { + months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'), + monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'), + weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'), + weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'), + weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'), + weekdaysParseExact : true, + // time formats are the same as en-gb + longDateFormat: { + LT: 'HH:mm', + LTS : 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd, D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[Heddiw am] LT', + nextDay: '[Yfory am] LT', + nextWeek: 'dddd [am] LT', + lastDay: '[Ddoe am] LT', + lastWeek: 'dddd [diwethaf am] LT', + sameElse: 'L' + }, + relativeTime: { + future: 'mewn %s', + past: '%s yn ôl', + s: 'ychydig eiliadau', + m: 'munud', + mm: '%d munud', + h: 'awr', + hh: '%d awr', + d: 'diwrnod', + dd: '%d diwrnod', + M: 'mis', + MM: '%d mis', + y: 'blwyddyn', + yy: '%d flynedd' + }, + ordinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/, + // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh + ordinal: function (number) { + var b = number, + output = '', + lookup = [ + '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed + 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed + ]; + if (b > 20) { + if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) { + output = 'fed'; // not 30ain, 70ain or 90ain + } else { + output = 'ain'; + } + } else if (b > 0) { + output = lookup[b]; + } + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return cy; + +}));
@@ -0,0 +1,60 @@
+//! moment.js locale configuration +//! locale : Danish [da] +//! author : Ulrik Nielsen : https://github.com/mrbase + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var da = moment.defineLocale('da', { + months : 'januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december'.split('_'), + monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'), + weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'), + weekdaysShort : 'søn_man_tir_ons_tor_fre_lør'.split('_'), + weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY HH:mm', + LLLL : 'dddd [d.] D. MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[I dag kl.] LT', + nextDay : '[I morgen kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[I går kl.] LT', + lastWeek : '[sidste] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'om %s', + past : '%s siden', + s : 'få sekunder', + m : 'et minut', + mm : '%d minutter', + h : 'en time', + hh : '%d timer', + d : 'en dag', + dd : '%d dage', + M : 'en måned', + MM : '%d måneder', + y : 'et år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return da; + +}));
@@ -0,0 +1,79 @@
+//! moment.js locale configuration +//! locale : German (Austria) [de-at] +//! author : lluchs : https://github.com/lluchs +//! author: Menelion Elensúle: https://github.com/Oire +//! author : Martin Groller : https://github.com/MadMG +//! author : Mikolaj Dadela : https://github.com/mik01aj + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eine Minute', 'einer Minute'], + 'h': ['eine Stunde', 'einer Stunde'], + 'd': ['ein Tag', 'einem Tag'], + 'dd': [number + ' Tage', number + ' Tagen'], + 'M': ['ein Monat', 'einem Monat'], + 'MM': [number + ' Monate', number + ' Monaten'], + 'y': ['ein Jahr', 'einem Jahr'], + 'yy': [number + ' Jahre', number + ' Jahren'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; + } + + var de_at = moment.defineLocale('de-at', { + months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort : 'Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + monthsParseExact : true, + weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'), + weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'), + weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY HH:mm', + LLLL : 'dddd, D. MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + relativeTime : { + future : 'in %s', + past : 'vor %s', + s : 'ein paar Sekunden', + m : processRelativeTime, + mm : '%d Minuten', + h : processRelativeTime, + hh : '%d Stunden', + d : processRelativeTime, + dd : processRelativeTime, + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return de_at; + +}));
@@ -0,0 +1,78 @@
+//! moment.js locale configuration +//! locale : German [de] +//! author : lluchs : https://github.com/lluchs +//! author: Menelion Elensúle: https://github.com/Oire +//! author : Mikolaj Dadela : https://github.com/mik01aj + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eine Minute', 'einer Minute'], + 'h': ['eine Stunde', 'einer Stunde'], + 'd': ['ein Tag', 'einem Tag'], + 'dd': [number + ' Tage', number + ' Tagen'], + 'M': ['ein Monat', 'einem Monat'], + 'MM': [number + ' Monate', number + ' Monaten'], + 'y': ['ein Jahr', 'einem Jahr'], + 'yy': [number + ' Jahre', number + ' Jahren'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; + } + + var de = moment.defineLocale('de', { + months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort : 'Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + monthsParseExact : true, + weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'), + weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'), + weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY HH:mm', + LLLL : 'dddd, D. MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + relativeTime : { + future : 'in %s', + past : 'vor %s', + s : 'ein paar Sekunden', + m : processRelativeTime, + mm : '%d Minuten', + h : processRelativeTime, + hh : '%d Stunden', + d : processRelativeTime, + dd : processRelativeTime, + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return de; + +}));
@@ -0,0 +1,99 @@
+//! moment.js locale configuration +//! locale : Maldivian [dv] +//! author : Jawish Hameed : https://github.com/jawish + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var months = [ + 'ޖެނުއަރީ', + 'ފެބްރުއަރީ', + 'މާރިޗު', + 'އޭޕްރީލު', + 'މޭ', + 'ޖޫން', + 'ޖުލައި', + 'އޯގަސްޓު', + 'ސެޕްޓެމްބަރު', + 'އޮކްޓޯބަރު', + 'ނޮވެމްބަރު', + 'ޑިސެމްބަރު' + ], weekdays = [ + 'އާދިއްތަ', + 'ހޯމަ', + 'އަންގާރަ', + 'ބުދަ', + 'ބުރާސްފަތި', + 'ހުކުރު', + 'ހޮނިހިރު' + ]; + + var dv = moment.defineLocale('dv', { + months : months, + monthsShort : months, + weekdays : weekdays, + weekdaysShort : weekdays, + weekdaysMin : 'އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި'.split('_'), + longDateFormat : { + + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'D/M/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + meridiemParse: /މކ|މފ/, + isPM : function (input) { + return 'މފ' === input; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'މކ'; + } else { + return 'މފ'; + } + }, + calendar : { + sameDay : '[މިއަދު] LT', + nextDay : '[މާދަމާ] LT', + nextWeek : 'dddd LT', + lastDay : '[އިއްޔެ] LT', + lastWeek : '[ފާއިތުވި] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : 'ތެރޭގައި %s', + past : 'ކުރިން %s', + s : 'ސިކުންތުކޮޅެއް', + m : 'މިނިޓެއް', + mm : 'މިނިޓު %d', + h : 'ގަޑިއިރެއް', + hh : 'ގަޑިއިރު %d', + d : 'ދުވަހެއް', + dd : 'ދުވަސް %d', + M : 'މަހެއް', + MM : 'މަސް %d', + y : 'އަހަރެއް', + yy : 'އަހަރު %d' + }, + preparse: function (string) { + return string.replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/,/g, '،'); + }, + week : { + dow : 7, // Sunday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + return dv; + +}));
@@ -0,0 +1,98 @@
+//! moment.js locale configuration +//! locale : Greek [el] +//! author : Aggelos Karalias : https://github.com/mehiel + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + function isFunction(input) { + return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]'; + } + + + var el = moment.defineLocale('el', { + monthsNominativeEl : 'Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος'.split('_'), + monthsGenitiveEl : 'Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου'.split('_'), + months : function (momentToFormat, format) { + if (/D/.test(format.substring(0, format.indexOf('MMMM')))) { // if there is a day number before 'MMMM' + return this._monthsGenitiveEl[momentToFormat.month()]; + } else { + return this._monthsNominativeEl[momentToFormat.month()]; + } + }, + monthsShort : 'Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ'.split('_'), + weekdays : 'Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο'.split('_'), + weekdaysShort : 'Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ'.split('_'), + weekdaysMin : 'Κυ_Δε_Τρ_Τε_Πε_Πα_Σα'.split('_'), + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'μμ' : 'ΜΜ'; + } else { + return isLower ? 'πμ' : 'ΠΜ'; + } + }, + isPM : function (input) { + return ((input + '').toLowerCase()[0] === 'μ'); + }, + meridiemParse : /[ΠΜ]\.?Μ?\.?/i, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendarEl : { + sameDay : '[Σήμερα {}] LT', + nextDay : '[Αύριο {}] LT', + nextWeek : 'dddd [{}] LT', + lastDay : '[Χθες {}] LT', + lastWeek : function () { + switch (this.day()) { + case 6: + return '[το προηγούμενο] dddd [{}] LT'; + default: + return '[την προηγούμενη] dddd [{}] LT'; + } + }, + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendarEl[key], + hours = mom && mom.hours(); + if (isFunction(output)) { + output = output.apply(mom); + } + return output.replace('{}', (hours % 12 === 1 ? 'στη' : 'στις')); + }, + relativeTime : { + future : 'σε %s', + past : '%s πριν', + s : 'λίγα δευτερόλεπτα', + m : 'ένα λεπτό', + mm : '%d λεπτά', + h : 'μία ώρα', + hh : '%d ώρες', + d : 'μία μέρα', + dd : '%d μέρες', + M : 'ένας μήνας', + MM : '%d μήνες', + y : 'ένας χρόνος', + yy : '%d χρόνια' + }, + ordinalParse: /\d{1,2}η/, + ordinal: '%dη', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4st is the first week of the year. + } + }); + + return el; + +}));
@@ -0,0 +1,66 @@
+//! moment.js locale configuration +//! locale : English (Australia) [en-au] + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var en_au = moment.defineLocale('en-au', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return en_au; + +}));
@@ -0,0 +1,63 @@
+//! moment.js locale configuration +//! locale : English (Canada) [en-ca] +//! author : Jonathan Abourbih : https://github.com/jonbca + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var en_ca = moment.defineLocale('en-ca', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'YYYY-MM-DD', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY h:mm A', + LLLL : 'dddd, MMMM D, YYYY h:mm A' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } + }); + + return en_ca; + +}));
@@ -0,0 +1,67 @@
+//! moment.js locale configuration +//! locale : English (United Kingdom) [en-gb] +//! author : Chris Gedrim : https://github.com/chrisgedrim + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var en_gb = moment.defineLocale('en-gb', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return en_gb; + +}));
@@ -0,0 +1,67 @@
+//! moment.js locale configuration +//! locale : English (Ireland) [en-ie] +//! author : Chris Cartlidge : https://github.com/chriscartlidge + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var en_ie = moment.defineLocale('en-ie', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return en_ie; + +}));
@@ -0,0 +1,66 @@
+//! moment.js locale configuration +//! locale : English (New Zealand) [en-nz] + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var en_nz = moment.defineLocale('en-nz', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return en_nz; + +}));
@@ -0,0 +1,73 @@
+//! moment.js locale configuration +//! locale : Esperanto [eo] +//! author : Colin Dean : https://github.com/colindean +//! komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko. +//! Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni! + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var eo = moment.defineLocale('eo', { + months : 'januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro'.split('_'), + monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec'.split('_'), + weekdays : 'Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato'.split('_'), + weekdaysShort : 'Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Ĵa_Ve_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'D[-an de] MMMM, YYYY', + LLL : 'D[-an de] MMMM, YYYY HH:mm', + LLLL : 'dddd, [la] D[-an de] MMMM, YYYY HH:mm' + }, + meridiemParse: /[ap]\.t\.m/i, + isPM: function (input) { + return input.charAt(0).toLowerCase() === 'p'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'p.t.m.' : 'P.T.M.'; + } else { + return isLower ? 'a.t.m.' : 'A.T.M.'; + } + }, + calendar : { + sameDay : '[Hodiaŭ je] LT', + nextDay : '[Morgaŭ je] LT', + nextWeek : 'dddd [je] LT', + lastDay : '[Hieraŭ je] LT', + lastWeek : '[pasinta] dddd [je] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'je %s', + past : 'antaŭ %s', + s : 'sekundoj', + m : 'minuto', + mm : '%d minutoj', + h : 'horo', + hh : '%d horoj', + d : 'tago',//ne 'diurno', ĉar estas uzita por proksimumo + dd : '%d tagoj', + M : 'monato', + MM : '%d monatoj', + y : 'jaro', + yy : '%d jaroj' + }, + ordinalParse: /\d{1,2}a/, + ordinal : '%da', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return eo; + +}));
@@ -0,0 +1,80 @@
+//! moment.js locale configuration +//! locale : Spanish (Dominican Republic) [es-do] + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_'), + monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_'); + + var es_do = moment.defineLocale('es-do', { + months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShort[m.month()]; + } else { + return monthsShortDot[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'), + weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'), + weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY h:mm A', + LLLL : 'dddd, D [de] MMMM [de] YYYY h:mm A' + }, + calendar : { + sameDay : function () { + return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextDay : function () { + return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastDay : function () { + return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'en %s', + past : 'hace %s', + s : 'unos segundos', + m : 'un minuto', + mm : '%d minutos', + h : 'una hora', + hh : '%d horas', + d : 'un día', + dd : '%d días', + M : 'un mes', + MM : '%d meses', + y : 'un año', + yy : '%d años' + }, + ordinalParse : /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return es_do; + +}));
@@ -0,0 +1,81 @@
+//! moment.js locale configuration +//! locale : Spanish [es] +//! author : Julio Napurí : https://github.com/julionc + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_'), + monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_'); + + var es = moment.defineLocale('es', { + months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShort[m.month()]; + } else { + return monthsShortDot[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'), + weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'), + weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY H:mm', + LLLL : 'dddd, D [de] MMMM [de] YYYY H:mm' + }, + calendar : { + sameDay : function () { + return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextDay : function () { + return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastDay : function () { + return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'en %s', + past : 'hace %s', + s : 'unos segundos', + m : 'un minuto', + mm : '%d minutos', + h : 'una hora', + hh : '%d horas', + d : 'un día', + dd : '%d días', + M : 'un mes', + MM : '%d meses', + y : 'un año', + yy : '%d años' + }, + ordinalParse : /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return es; + +}));
@@ -0,0 +1,80 @@
+//! moment.js locale configuration +//! locale : Estonian [et] +//! author : Henry Kehlmann : https://github.com/madhenry +//! improvements : Illimar Tambek : https://github.com/ragulka + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'], + 'm' : ['ühe minuti', 'üks minut'], + 'mm': [number + ' minuti', number + ' minutit'], + 'h' : ['ühe tunni', 'tund aega', 'üks tund'], + 'hh': [number + ' tunni', number + ' tundi'], + 'd' : ['ühe päeva', 'üks päev'], + 'M' : ['kuu aja', 'kuu aega', 'üks kuu'], + 'MM': [number + ' kuu', number + ' kuud'], + 'y' : ['ühe aasta', 'aasta', 'üks aasta'], + 'yy': [number + ' aasta', number + ' aastat'] + }; + if (withoutSuffix) { + return format[key][2] ? format[key][2] : format[key][1]; + } + return isFuture ? format[key][0] : format[key][1]; + } + + var et = moment.defineLocale('et', { + months : 'jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember'.split('_'), + monthsShort : 'jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets'.split('_'), + weekdays : 'pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev'.split('_'), + weekdaysShort : 'P_E_T_K_N_R_L'.split('_'), + weekdaysMin : 'P_E_T_K_N_R_L'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[Täna,] LT', + nextDay : '[Homme,] LT', + nextWeek : '[Järgmine] dddd LT', + lastDay : '[Eile,] LT', + lastWeek : '[Eelmine] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s pärast', + past : '%s tagasi', + s : processRelativeTime, + m : processRelativeTime, + mm : processRelativeTime, + h : processRelativeTime, + hh : processRelativeTime, + d : processRelativeTime, + dd : '%d päeva', + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return et; + +}));
@@ -0,0 +1,66 @@
+//! moment.js locale configuration +//! locale : Basque [eu] +//! author : Eneko Illarramendi : https://github.com/eillarra + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var eu = moment.defineLocale('eu', { + months : 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split('_'), + monthsShort : 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split('_'), + monthsParseExact : true, + weekdays : 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split('_'), + weekdaysShort : 'ig._al._ar._az._og._ol._lr.'.split('_'), + weekdaysMin : 'ig_al_ar_az_og_ol_lr'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'YYYY[ko] MMMM[ren] D[a]', + LLL : 'YYYY[ko] MMMM[ren] D[a] HH:mm', + LLLL : 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm', + l : 'YYYY-M-D', + ll : 'YYYY[ko] MMM D[a]', + lll : 'YYYY[ko] MMM D[a] HH:mm', + llll : 'ddd, YYYY[ko] MMM D[a] HH:mm' + }, + calendar : { + sameDay : '[gaur] LT[etan]', + nextDay : '[bihar] LT[etan]', + nextWeek : 'dddd LT[etan]', + lastDay : '[atzo] LT[etan]', + lastWeek : '[aurreko] dddd LT[etan]', + sameElse : 'L' + }, + relativeTime : { + future : '%s barru', + past : 'duela %s', + s : 'segundo batzuk', + m : 'minutu bat', + mm : '%d minutu', + h : 'ordu bat', + hh : '%d ordu', + d : 'egun bat', + dd : '%d egun', + M : 'hilabete bat', + MM : '%d hilabete', + y : 'urte bat', + yy : '%d urte' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return eu; + +}));
@@ -0,0 +1,106 @@
+//! moment.js locale configuration +//! locale : Persian [fa] +//! author : Ebrahim Byagowi : https://github.com/ebraminio + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '۱', + '2': '۲', + '3': '۳', + '4': '۴', + '5': '۵', + '6': '۶', + '7': '۷', + '8': '۸', + '9': '۹', + '0': '۰' + }, numberMap = { + '۱': '1', + '۲': '2', + '۳': '3', + '۴': '4', + '۵': '5', + '۶': '6', + '۷': '7', + '۸': '8', + '۹': '9', + '۰': '0' + }; + + var fa = moment.defineLocale('fa', { + months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + meridiemParse: /قبل از ظهر|بعد از ظهر/, + isPM: function (input) { + return /بعد از ظهر/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'قبل از ظهر'; + } else { + return 'بعد از ظهر'; + } + }, + calendar : { + sameDay : '[امروز ساعت] LT', + nextDay : '[فردا ساعت] LT', + nextWeek : 'dddd [ساعت] LT', + lastDay : '[دیروز ساعت] LT', + lastWeek : 'dddd [پیش] [ساعت] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'در %s', + past : '%s پیش', + s : 'چندین ثانیه', + m : 'یک دقیقه', + mm : '%d دقیقه', + h : 'یک ساعت', + hh : '%d ساعت', + d : 'یک روز', + dd : '%d روز', + M : 'یک ماه', + MM : '%d ماه', + y : 'یک سال', + yy : '%d سال' + }, + preparse: function (string) { + return string.replace(/[۰-۹]/g, function (match) { + return numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }).replace(/,/g, '،'); + }, + ordinalParse: /\d{1,2}م/, + ordinal : '%dم', + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + return fa; + +}));
@@ -0,0 +1,107 @@
+//! moment.js locale configuration +//! locale : Finnish [fi] +//! author : Tarmo Aidantausta : https://github.com/bleadof + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '), + numbersFuture = [ + 'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden', + numbersPast[7], numbersPast[8], numbersPast[9] + ]; + function translate(number, withoutSuffix, key, isFuture) { + var result = ''; + switch (key) { + case 's': + return isFuture ? 'muutaman sekunnin' : 'muutama sekunti'; + case 'm': + return isFuture ? 'minuutin' : 'minuutti'; + case 'mm': + result = isFuture ? 'minuutin' : 'minuuttia'; + break; + case 'h': + return isFuture ? 'tunnin' : 'tunti'; + case 'hh': + result = isFuture ? 'tunnin' : 'tuntia'; + break; + case 'd': + return isFuture ? 'päivän' : 'päivä'; + case 'dd': + result = isFuture ? 'päivän' : 'päivää'; + break; + case 'M': + return isFuture ? 'kuukauden' : 'kuukausi'; + case 'MM': + result = isFuture ? 'kuukauden' : 'kuukautta'; + break; + case 'y': + return isFuture ? 'vuoden' : 'vuosi'; + case 'yy': + result = isFuture ? 'vuoden' : 'vuotta'; + break; + } + result = verbalNumber(number, isFuture) + ' ' + result; + return result; + } + function verbalNumber(number, isFuture) { + return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number; + } + + var fi = moment.defineLocale('fi', { + months : 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split('_'), + monthsShort : 'tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu'.split('_'), + weekdays : 'sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai'.split('_'), + weekdaysShort : 'su_ma_ti_ke_to_pe_la'.split('_'), + weekdaysMin : 'su_ma_ti_ke_to_pe_la'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD.MM.YYYY', + LL : 'Do MMMM[ta] YYYY', + LLL : 'Do MMMM[ta] YYYY, [klo] HH.mm', + LLLL : 'dddd, Do MMMM[ta] YYYY, [klo] HH.mm', + l : 'D.M.YYYY', + ll : 'Do MMM YYYY', + lll : 'Do MMM YYYY, [klo] HH.mm', + llll : 'ddd, Do MMM YYYY, [klo] HH.mm' + }, + calendar : { + sameDay : '[tänään] [klo] LT', + nextDay : '[huomenna] [klo] LT', + nextWeek : 'dddd [klo] LT', + lastDay : '[eilen] [klo] LT', + lastWeek : '[viime] dddd[na] [klo] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s päästä', + past : '%s sitten', + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return fi; + +}));
@@ -0,0 +1,60 @@
+//! moment.js locale configuration +//! locale : Faroese [fo] +//! author : Ragnar Johannesen : https://github.com/ragnar123 + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var fo = moment.defineLocale('fo', { + months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), + weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'), + weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'), + weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D. MMMM, YYYY HH:mm' + }, + calendar : { + sameDay : '[Í dag kl.] LT', + nextDay : '[Í morgin kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[Í gjár kl.] LT', + lastWeek : '[síðstu] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'um %s', + past : '%s síðani', + s : 'fá sekund', + m : 'ein minutt', + mm : '%d minuttir', + h : 'ein tími', + hh : '%d tímar', + d : 'ein dagur', + dd : '%d dagar', + M : 'ein mánaði', + MM : '%d mánaðir', + y : 'eitt ár', + yy : '%d ár' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return fo; + +}));
@@ -0,0 +1,60 @@
+//! moment.js locale configuration +//! locale : French (Canada) [fr-ca] +//! author : Jonathan Abourbih : https://github.com/jonbca + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var fr_ca = moment.defineLocale('fr-ca', { + months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), + monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), + monthsParseExact : true, + weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), + weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Aujourd\'hui à] LT', + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dans %s', + past : 'il y a %s', + s : 'quelques secondes', + m : 'une minute', + mm : '%d minutes', + h : 'une heure', + hh : '%d heures', + d : 'un jour', + dd : '%d jours', + M : 'un mois', + MM : '%d mois', + y : 'un an', + yy : '%d ans' + }, + ordinalParse: /\d{1,2}(er|e)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : 'e'); + } + }); + + return fr_ca; + +}));
@@ -0,0 +1,64 @@
+//! moment.js locale configuration +//! locale : French (Switzerland) [fr-ch] +//! author : Gaspard Bucher : https://github.com/gaspard + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var fr_ch = moment.defineLocale('fr-ch', { + months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), + monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), + monthsParseExact : true, + weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), + weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Aujourd\'hui à] LT', + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dans %s', + past : 'il y a %s', + s : 'quelques secondes', + m : 'une minute', + mm : '%d minutes', + h : 'une heure', + hh : '%d heures', + d : 'un jour', + dd : '%d jours', + M : 'un mois', + MM : '%d mois', + y : 'un an', + yy : '%d ans' + }, + ordinalParse: /\d{1,2}(er|e)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : 'e'); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return fr_ch; + +}));
@@ -0,0 +1,64 @@
+//! moment.js locale configuration +//! locale : French [fr] +//! author : John Fischer : https://github.com/jfroffice + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var fr = moment.defineLocale('fr', { + months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), + monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), + monthsParseExact : true, + weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), + weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Aujourd\'hui à] LT', + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dans %s', + past : 'il y a %s', + s : 'quelques secondes', + m : 'une minute', + mm : '%d minutes', + h : 'une heure', + hh : '%d heures', + d : 'un jour', + dd : '%d jours', + M : 'un mois', + MM : '%d mois', + y : 'un an', + yy : '%d ans' + }, + ordinalParse: /\d{1,2}(er|)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : ''); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return fr; + +}));
@@ -0,0 +1,73 @@
+//! moment.js locale configuration +//! locale : Frisian [fy] +//! author : Robin van der Vliet : https://github.com/robin0van0der0v + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_'), + monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'); + + var fy = moment.defineLocale('fy', { + months : 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShortWithoutDots[m.month()]; + } else { + return monthsShortWithDots[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split('_'), + weekdaysShort : 'si._mo._ti._wo._to._fr._so.'.split('_'), + weekdaysMin : 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[hjoed om] LT', + nextDay: '[moarn om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[juster om] LT', + lastWeek: '[ôfrûne] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'oer %s', + past : '%s lyn', + s : 'in pear sekonden', + m : 'ien minút', + mm : '%d minuten', + h : 'ien oere', + hh : '%d oeren', + d : 'ien dei', + dd : '%d dagen', + M : 'ien moanne', + MM : '%d moannen', + y : 'ien jier', + yy : '%d jierren' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return fy; + +}));
@@ -0,0 +1,76 @@
+//! moment.js locale configuration +//! locale : Scottish Gaelic [gd] +//! author : Jon Ashdown : https://github.com/jonashdown + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var months = [ + 'Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean', 'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal', 'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd' + ]; + + var monthsShort = ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh']; + + var weekdays = ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne']; + + var weekdaysShort = ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis']; + + var weekdaysMin = ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa']; + + var gd = moment.defineLocale('gd', { + months : months, + monthsShort : monthsShort, + monthsParseExact : true, + weekdays : weekdays, + weekdaysShort : weekdaysShort, + weekdaysMin : weekdaysMin, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[An-diugh aig] LT', + nextDay : '[A-màireach aig] LT', + nextWeek : 'dddd [aig] LT', + lastDay : '[An-dè aig] LT', + lastWeek : 'dddd [seo chaidh] [aig] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'ann an %s', + past : 'bho chionn %s', + s : 'beagan diogan', + m : 'mionaid', + mm : '%d mionaidean', + h : 'uair', + hh : '%d uairean', + d : 'latha', + dd : '%d latha', + M : 'mìos', + MM : '%d mìosan', + y : 'bliadhna', + yy : '%d bliadhna' + }, + ordinalParse : /\d{1,2}(d|na|mh)/, + ordinal : function (number) { + var output = number === 1 ? 'd' : number % 10 === 2 ? 'na' : 'mh'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return gd; + +}));
@@ -0,0 +1,77 @@
+//! moment.js locale configuration +//! locale : Galician [gl] +//! author : Juan G. Hurtado : https://github.com/juanghurtado + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var gl = moment.defineLocale('gl', { + months : 'Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro'.split('_'), + monthsShort : 'Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.'.split('_'), + monthsParseExact: true, + weekdays : 'Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado'.split('_'), + weekdaysShort : 'Dom._Lun._Mar._Mér._Xov._Ven._Sáb.'.split('_'), + weekdaysMin : 'Do_Lu_Ma_Mé_Xo_Ve_Sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd D MMMM YYYY H:mm' + }, + calendar : { + sameDay : function () { + return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; + }, + nextDay : function () { + return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; + }, + nextWeek : function () { + return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + lastDay : function () { + return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT'; + }, + lastWeek : function () { + return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : function (str) { + if (str === 'uns segundos') { + return 'nuns segundos'; + } + return 'en ' + str; + }, + past : 'hai %s', + s : 'uns segundos', + m : 'un minuto', + mm : '%d minutos', + h : 'unha hora', + hh : '%d horas', + d : 'un día', + dd : '%d días', + M : 'un mes', + MM : '%d meses', + y : 'un ano', + yy : '%d anos' + }, + ordinalParse : /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return gl; + +}));
@@ -0,0 +1,99 @@
+//! moment.js locale configuration +//! locale : Hebrew [he] +//! author : Tomer Cohen : https://github.com/tomer +//! author : Moshe Simantov : https://github.com/DevelopmentIL +//! author : Tal Ater : https://github.com/TalAter + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var he = moment.defineLocale('he', { + months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'), + monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'), + weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'), + weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'), + weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [ב]MMMM YYYY', + LLL : 'D [ב]MMMM YYYY HH:mm', + LLLL : 'dddd, D [ב]MMMM YYYY HH:mm', + l : 'D/M/YYYY', + ll : 'D MMM YYYY', + lll : 'D MMM YYYY HH:mm', + llll : 'ddd, D MMM YYYY HH:mm' + }, + calendar : { + sameDay : '[היום ב־]LT', + nextDay : '[מחר ב־]LT', + nextWeek : 'dddd [בשעה] LT', + lastDay : '[אתמול ב־]LT', + lastWeek : '[ביום] dddd [האחרון בשעה] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'בעוד %s', + past : 'לפני %s', + s : 'מספר שניות', + m : 'דקה', + mm : '%d דקות', + h : 'שעה', + hh : function (number) { + if (number === 2) { + return 'שעתיים'; + } + return number + ' שעות'; + }, + d : 'יום', + dd : function (number) { + if (number === 2) { + return 'יומיים'; + } + return number + ' ימים'; + }, + M : 'חודש', + MM : function (number) { + if (number === 2) { + return 'חודשיים'; + } + return number + ' חודשים'; + }, + y : 'שנה', + yy : function (number) { + if (number === 2) { + return 'שנתיים'; + } else if (number % 10 === 0 && number !== 10) { + return number + ' שנה'; + } + return number + ' שנים'; + } + }, + meridiemParse: /אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i, + isPM : function (input) { + return /^(אחה"צ|אחרי הצהריים|בערב)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 5) { + return 'לפנות בוקר'; + } else if (hour < 10) { + return 'בבוקר'; + } else if (hour < 12) { + return isLower ? 'לפנה"צ' : 'לפני הצהריים'; + } else if (hour < 18) { + return isLower ? 'אחה"צ' : 'אחרי הצהריים'; + } else { + return 'בערב'; + } + } + }); + + return he; + +}));
@@ -0,0 +1,124 @@
+//! moment.js locale configuration +//! locale : Hindi [hi] +//! author : Mayank Singhal : https://github.com/mayanksinghal + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var hi = moment.defineLocale('hi', { + months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'), + monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'), + monthsParseExact: true, + weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm बजे', + LTS : 'A h:mm:ss बजे', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm बजे', + LLLL : 'dddd, D MMMM YYYY, A h:mm बजे' + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[कल] LT', + nextWeek : 'dddd, LT', + lastDay : '[कल] LT', + lastWeek : '[पिछले] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s में', + past : '%s पहले', + s : 'कुछ ही क्षण', + m : 'एक मिनट', + mm : '%d मिनट', + h : 'एक घंटा', + hh : '%d घंटे', + d : 'एक दिन', + dd : '%d दिन', + M : 'एक महीने', + MM : '%d महीने', + y : 'एक वर्ष', + yy : '%d वर्ष' + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + // Hindi notation for meridiems are quite fuzzy in practice. While there exists + // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi. + meridiemParse: /रात|सुबह|दोपहर|शाम/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सुबह') { + return hour; + } else if (meridiem === 'दोपहर') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'शाम') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'रात'; + } else if (hour < 10) { + return 'सुबह'; + } else if (hour < 17) { + return 'दोपहर'; + } else if (hour < 20) { + return 'शाम'; + } else { + return 'रात'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + return hi; + +}));
@@ -0,0 +1,145 @@
+//! moment.js locale configuration +//! locale : Croatian [hr] +//! author : Bojan Marković : https://github.com/bmarkovic + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } + } + + var hr = moment.defineLocale('hr', { + months : { + format: 'siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca'.split('_'), + standalone: 'siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_') + }, + monthsShort : 'sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'), + monthsParseExact: true, + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : translate, + mm : translate, + h : translate, + hh : translate, + d : 'dan', + dd : translate, + M : 'mjesec', + MM : translate, + y : 'godinu', + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return hr; + +}));
@@ -0,0 +1,109 @@
+//! moment.js locale configuration +//! locale : Hungarian [hu] +//! author : Adam Brunner : https://github.com/adambrunner + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' '); + function translate(number, withoutSuffix, key, isFuture) { + var num = number, + suffix; + switch (key) { + case 's': + return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce'; + case 'm': + return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce'); + case 'mm': + return num + (isFuture || withoutSuffix ? ' perc' : ' perce'); + case 'h': + return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája'); + case 'hh': + return num + (isFuture || withoutSuffix ? ' óra' : ' órája'); + case 'd': + return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja'); + case 'dd': + return num + (isFuture || withoutSuffix ? ' nap' : ' napja'); + case 'M': + return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); + case 'MM': + return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); + case 'y': + return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve'); + case 'yy': + return num + (isFuture || withoutSuffix ? ' év' : ' éve'); + } + return ''; + } + function week(isFuture) { + return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]'; + } + + var hu = moment.defineLocale('hu', { + months : 'január_február_március_április_május_június_július_augusztus_szeptember_október_november_december'.split('_'), + monthsShort : 'jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec'.split('_'), + weekdays : 'vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat'.split('_'), + weekdaysShort : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'), + weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'YYYY.MM.DD.', + LL : 'YYYY. MMMM D.', + LLL : 'YYYY. MMMM D. H:mm', + LLLL : 'YYYY. MMMM D., dddd H:mm' + }, + meridiemParse: /de|du/i, + isPM: function (input) { + return input.charAt(1).toLowerCase() === 'u'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower === true ? 'de' : 'DE'; + } else { + return isLower === true ? 'du' : 'DU'; + } + }, + calendar : { + sameDay : '[ma] LT[-kor]', + nextDay : '[holnap] LT[-kor]', + nextWeek : function () { + return week.call(this, true); + }, + lastDay : '[tegnap] LT[-kor]', + lastWeek : function () { + return week.call(this, false); + }, + sameElse : 'L' + }, + relativeTime : { + future : '%s múlva', + past : '%s', + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return hu; + +}));
@@ -0,0 +1,95 @@
+//! moment.js locale configuration +//! locale : Armenian [hy-am] +//! author : Armendarabyan : https://github.com/armendarabyan + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var hy_am = moment.defineLocale('hy-am', { + months : { + format: 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_'), + standalone: 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_') + }, + monthsShort : 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'), + weekdays : 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_'), + weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY թ.', + LLL : 'D MMMM YYYY թ., HH:mm', + LLLL : 'dddd, D MMMM YYYY թ., HH:mm' + }, + calendar : { + sameDay: '[այսօր] LT', + nextDay: '[վաղը] LT', + lastDay: '[երեկ] LT', + nextWeek: function () { + return 'dddd [օրը ժամը] LT'; + }, + lastWeek: function () { + return '[անցած] dddd [օրը ժամը] LT'; + }, + sameElse: 'L' + }, + relativeTime : { + future : '%s հետո', + past : '%s առաջ', + s : 'մի քանի վայրկյան', + m : 'րոպե', + mm : '%d րոպե', + h : 'ժամ', + hh : '%d ժամ', + d : 'օր', + dd : '%d օր', + M : 'ամիս', + MM : '%d ամիս', + y : 'տարի', + yy : '%d տարի' + }, + meridiemParse: /գիշերվա|առավոտվա|ցերեկվա|երեկոյան/, + isPM: function (input) { + return /^(ցերեկվա|երեկոյան)$/.test(input); + }, + meridiem : function (hour) { + if (hour < 4) { + return 'գիշերվա'; + } else if (hour < 12) { + return 'առավոտվա'; + } else if (hour < 17) { + return 'ցերեկվա'; + } else { + return 'երեկոյան'; + } + }, + ordinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/, + ordinal: function (number, period) { + switch (period) { + case 'DDD': + case 'w': + case 'W': + case 'DDDo': + if (number === 1) { + return number + '-ին'; + } + return number + '-րդ'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return hy_am; + +}));
@@ -0,0 +1,83 @@
+//! moment.js locale configuration +//! locale : Indonesian [id] +//! author : Mohammad Satrio Utomo : https://github.com/tyok +//! reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var id = moment.defineLocale('id', { + months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu'.split('_'), + weekdaysShort : 'Min_Sen_Sel_Rab_Kam_Jum_Sab'.split('_'), + weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sb'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /pagi|siang|sore|malam/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'siang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sore' || meridiem === 'malam') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'siang'; + } else if (hours < 19) { + return 'sore'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Besok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kemarin pukul] LT', + lastWeek : 'dddd [lalu pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'dalam %s', + past : '%s yang lalu', + s : 'beberapa detik', + m : 'semenit', + mm : '%d menit', + h : 'sejam', + hh : '%d jam', + d : 'sehari', + dd : '%d hari', + M : 'sebulan', + MM : '%d bulan', + y : 'setahun', + yy : '%d tahun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return id; + +}));
@@ -0,0 +1,127 @@
+//! moment.js locale configuration +//! locale : Icelandic [is] +//! author : Hinrik Örn Sigurðsson : https://github.com/hinrik + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function plural(n) { + if (n % 100 === 11) { + return true; + } else if (n % 10 === 1) { + return false; + } + return true; + } + function translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum'; + case 'm': + return withoutSuffix ? 'mínúta' : 'mínútu'; + case 'mm': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum'); + } else if (withoutSuffix) { + return result + 'mínúta'; + } + return result + 'mínútu'; + case 'hh': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum'); + } + return result + 'klukkustund'; + case 'd': + if (withoutSuffix) { + return 'dagur'; + } + return isFuture ? 'dag' : 'degi'; + case 'dd': + if (plural(number)) { + if (withoutSuffix) { + return result + 'dagar'; + } + return result + (isFuture ? 'daga' : 'dögum'); + } else if (withoutSuffix) { + return result + 'dagur'; + } + return result + (isFuture ? 'dag' : 'degi'); + case 'M': + if (withoutSuffix) { + return 'mánuður'; + } + return isFuture ? 'mánuð' : 'mánuði'; + case 'MM': + if (plural(number)) { + if (withoutSuffix) { + return result + 'mánuðir'; + } + return result + (isFuture ? 'mánuði' : 'mánuðum'); + } else if (withoutSuffix) { + return result + 'mánuður'; + } + return result + (isFuture ? 'mánuð' : 'mánuði'); + case 'y': + return withoutSuffix || isFuture ? 'ár' : 'ári'; + case 'yy': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'ár' : 'árum'); + } + return result + (withoutSuffix || isFuture ? 'ár' : 'ári'); + } + } + + var is = moment.defineLocale('is', { + months : 'janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des'.split('_'), + weekdays : 'sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur'.split('_'), + weekdaysShort : 'sun_mán_þri_mið_fim_fös_lau'.split('_'), + weekdaysMin : 'Su_Má_Þr_Mi_Fi_Fö_La'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] H:mm', + LLLL : 'dddd, D. MMMM YYYY [kl.] H:mm' + }, + calendar : { + sameDay : '[í dag kl.] LT', + nextDay : '[á morgun kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[í gær kl.] LT', + lastWeek : '[síðasta] dddd [kl.] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'eftir %s', + past : 'fyrir %s síðan', + s : translate, + m : translate, + mm : translate, + h : 'klukkustund', + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return is; + +}));
@@ -0,0 +1,70 @@
+//! moment.js locale configuration +//! locale : Italian [it] +//! author : Lorenzo : https://github.com/aliem +//! author: Mattia Larentis: https://github.com/nostalgiaz + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var it = moment.defineLocale('it', { + months : 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split('_'), + monthsShort : 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'), + weekdays : 'Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato'.split('_'), + weekdaysShort : 'Dom_Lun_Mar_Mer_Gio_Ven_Sab'.split('_'), + weekdaysMin : 'Do_Lu_Ma_Me_Gi_Ve_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Oggi alle] LT', + nextDay: '[Domani alle] LT', + nextWeek: 'dddd [alle] LT', + lastDay: '[Ieri alle] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[la scorsa] dddd [alle] LT'; + default: + return '[lo scorso] dddd [alle] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : function (s) { + return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s; + }, + past : '%s fa', + s : 'alcuni secondi', + m : 'un minuto', + mm : '%d minuti', + h : 'un\'ora', + hh : '%d ore', + d : 'un giorno', + dd : '%d giorni', + M : 'un mese', + MM : '%d mesi', + y : 'un anno', + yy : '%d anni' + }, + ordinalParse : /\d{1,2}º/, + ordinal: '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return it; + +}));
@@ -0,0 +1,76 @@
+//! moment.js locale configuration +//! locale : Japanese [ja] +//! author : LI Long : https://github.com/baryon + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ja = moment.defineLocale('ja', { + months : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + weekdays : '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'), + weekdaysShort : '日_月_火_水_木_金_土'.split('_'), + weekdaysMin : '日_月_火_水_木_金_土'.split('_'), + longDateFormat : { + LT : 'Ah時m分', + LTS : 'Ah時m分s秒', + L : 'YYYY/MM/DD', + LL : 'YYYY年M月D日', + LLL : 'YYYY年M月D日Ah時m分', + LLLL : 'YYYY年M月D日Ah時m分 dddd' + }, + meridiemParse: /午前|午後/i, + isPM : function (input) { + return input === '午後'; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return '午前'; + } else { + return '午後'; + } + }, + calendar : { + sameDay : '[今日] LT', + nextDay : '[明日] LT', + nextWeek : '[来週]dddd LT', + lastDay : '[昨日] LT', + lastWeek : '[前週]dddd LT', + sameElse : 'L' + }, + ordinalParse : /\d{1,2}日/, + ordinal : function (number, period) { + switch (period) { + case 'd': + case 'D': + case 'DDD': + return number + '日'; + default: + return number; + } + }, + relativeTime : { + future : '%s後', + past : '%s前', + s : '数秒', + m : '1分', + mm : '%d分', + h : '1時間', + hh : '%d時間', + d : '1日', + dd : '%d日', + M : '1ヶ月', + MM : '%dヶ月', + y : '1年', + yy : '%d年' + } + }); + + return ja; + +}));
@@ -0,0 +1,83 @@
+//! moment.js locale configuration +//! locale : Japanese [jv] +//! author : Rony Lantip : https://github.com/lantip +//! reference: http://jv.wikipedia.org/wiki/Basa_Jawa + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var jv = moment.defineLocale('jv', { + months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des'.split('_'), + weekdays : 'Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu'.split('_'), + weekdaysShort : 'Min_Sen_Sel_Reb_Kem_Jem_Sep'.split('_'), + weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sp'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /enjing|siyang|sonten|ndalu/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'enjing') { + return hour; + } else if (meridiem === 'siyang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sonten' || meridiem === 'ndalu') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'enjing'; + } else if (hours < 15) { + return 'siyang'; + } else if (hours < 19) { + return 'sonten'; + } else { + return 'ndalu'; + } + }, + calendar : { + sameDay : '[Dinten puniko pukul] LT', + nextDay : '[Mbenjang pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kala wingi pukul] LT', + lastWeek : 'dddd [kepengker pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'wonten ing %s', + past : '%s ingkang kepengker', + s : 'sawetawis detik', + m : 'setunggal menit', + mm : '%d menit', + h : 'setunggal jam', + hh : '%d jam', + d : 'sedinten', + dd : '%d dinten', + M : 'sewulan', + MM : '%d wulan', + y : 'setaun', + yy : '%d taun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return jv; + +}));
@@ -0,0 +1,89 @@
+//! moment.js locale configuration +//! locale : Georgian [ka] +//! author : Irakli Janiashvili : https://github.com/irakli-janiashvili + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ka = moment.defineLocale('ka', { + months : { + standalone: 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'), + format: 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_') + }, + monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'), + weekdays : { + standalone: 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'), + format: 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_'), + isFormat: /(წინა|შემდეგ)/ + }, + weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'), + weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[დღეს] LT[-ზე]', + nextDay : '[ხვალ] LT[-ზე]', + lastDay : '[გუშინ] LT[-ზე]', + nextWeek : '[შემდეგ] dddd LT[-ზე]', + lastWeek : '[წინა] dddd LT-ზე', + sameElse : 'L' + }, + relativeTime : { + future : function (s) { + return (/(წამი|წუთი|საათი|წელი)/).test(s) ? + s.replace(/ი$/, 'ში') : + s + 'ში'; + }, + past : function (s) { + if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) { + return s.replace(/(ი|ე)$/, 'ის წინ'); + } + if ((/წელი/).test(s)) { + return s.replace(/წელი$/, 'წლის წინ'); + } + }, + s : 'რამდენიმე წამი', + m : 'წუთი', + mm : '%d წუთი', + h : 'საათი', + hh : '%d საათი', + d : 'დღე', + dd : '%d დღე', + M : 'თვე', + MM : '%d თვე', + y : 'წელი', + yy : '%d წელი' + }, + ordinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/, + ordinal : function (number) { + if (number === 0) { + return number; + } + if (number === 1) { + return number + '-ლი'; + } + if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) { + return 'მე-' + number; + } + return number + '-ე'; + }, + week : { + dow : 1, + doy : 7 + } + }); + + return ka; + +}));
@@ -0,0 +1,87 @@
+//! moment.js locale configuration +//! locale : Kazakh [kk] +//! authors : Nurlan Rakhimzhanov : https://github.com/nurlan + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var suffixes = { + 0: '-ші', + 1: '-ші', + 2: '-ші', + 3: '-ші', + 4: '-ші', + 5: '-ші', + 6: '-шы', + 7: '-ші', + 8: '-ші', + 9: '-шы', + 10: '-шы', + 20: '-шы', + 30: '-шы', + 40: '-шы', + 50: '-ші', + 60: '-шы', + 70: '-ші', + 80: '-ші', + 90: '-шы', + 100: '-ші' + }; + + var kk = moment.defineLocale('kk', { + months : 'қаңтар_ақпан_наурыз_сәуір_мамыр_маусым_шілде_тамыз_қыркүйек_қазан_қараша_желтоқсан'.split('_'), + monthsShort : 'қаң_ақп_нау_сәу_мам_мау_шіл_там_қыр_қаз_қар_жел'.split('_'), + weekdays : 'жексенбі_дүйсенбі_сейсенбі_сәрсенбі_бейсенбі_жұма_сенбі'.split('_'), + weekdaysShort : 'жек_дүй_сей_сәр_бей_жұм_сен'.split('_'), + weekdaysMin : 'жк_дй_сй_ср_бй_жм_сн'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Бүгін сағат] LT', + nextDay : '[Ертең сағат] LT', + nextWeek : 'dddd [сағат] LT', + lastDay : '[Кеше сағат] LT', + lastWeek : '[Өткен аптаның] dddd [сағат] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ішінде', + past : '%s бұрын', + s : 'бірнеше секунд', + m : 'бір минут', + mm : '%d минут', + h : 'бір сағат', + hh : '%d сағат', + d : 'бір күн', + dd : '%d күн', + M : 'бір ай', + MM : '%d ай', + y : 'бір жыл', + yy : '%d жыл' + }, + ordinalParse: /\d{1,2}-(ші|шы)/, + ordinal : function (number) { + var a = number % 10, + b = number >= 100 ? 100 : null; + return number + (suffixes[number] || suffixes[a] || suffixes[b]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return kk; + +}));
@@ -0,0 +1,58 @@
+//! moment.js locale configuration +//! locale : Cambodian [km] +//! author : Kruy Vanna : https://github.com/kruyvanna + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var km = moment.defineLocale('km', { + months: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + monthsShort: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + longDateFormat: { + LT: 'HH:mm', + LTS : 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd, D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[ថ្ងៃនេះ ម៉ោង] LT', + nextDay: '[ស្អែក ម៉ោង] LT', + nextWeek: 'dddd [ម៉ោង] LT', + lastDay: '[ម្សិលមិញ ម៉ោង] LT', + lastWeek: 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT', + sameElse: 'L' + }, + relativeTime: { + future: '%sទៀត', + past: '%sមុន', + s: 'ប៉ុន្មានវិនាទី', + m: 'មួយនាទី', + mm: '%d នាទី', + h: 'មួយម៉ោង', + hh: '%d ម៉ោង', + d: 'មួយថ្ងៃ', + dd: '%d ថ្ងៃ', + M: 'មួយខែ', + MM: '%d ខែ', + y: 'មួយឆ្នាំ', + yy: '%d ឆ្នាំ' + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return km; + +}));
@@ -0,0 +1,68 @@
+//! moment.js locale configuration +//! locale : Korean [ko] +//! +//! authors +//! +//! - Kyungwook, Park : https://github.com/kyungw00k +//! - Jeeeyul Lee <jeeeyul@gmail.com> + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ko = moment.defineLocale('ko', { + months : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'), + monthsShort : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'), + weekdays : '일요일_월요일_화요일_수요일_목요일_금요일_토요일'.split('_'), + weekdaysShort : '일_월_화_수_목_금_토'.split('_'), + weekdaysMin : '일_월_화_수_목_금_토'.split('_'), + longDateFormat : { + LT : 'A h시 m분', + LTS : 'A h시 m분 s초', + L : 'YYYY.MM.DD', + LL : 'YYYY년 MMMM D일', + LLL : 'YYYY년 MMMM D일 A h시 m분', + LLLL : 'YYYY년 MMMM D일 dddd A h시 m분' + }, + calendar : { + sameDay : '오늘 LT', + nextDay : '내일 LT', + nextWeek : 'dddd LT', + lastDay : '어제 LT', + lastWeek : '지난주 dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s 후', + past : '%s 전', + s : '몇 초', + ss : '%d초', + m : '일분', + mm : '%d분', + h : '한 시간', + hh : '%d시간', + d : '하루', + dd : '%d일', + M : '한 달', + MM : '%d달', + y : '일 년', + yy : '%d년' + }, + ordinalParse : /\d{1,2}일/, + ordinal : '%d일', + meridiemParse : /오전|오후/, + isPM : function (token) { + return token === '오후'; + }, + meridiem : function (hour, minute, isUpper) { + return hour < 12 ? '오전' : '오후'; + } + }); + + return ko; + +}));
@@ -0,0 +1,88 @@
+//! moment.js locale configuration +//! locale : Kyrgyz [ky] +//! author : Chyngyz Arystan uulu : https://github.com/chyngyz + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + + var suffixes = { + 0: '-чү', + 1: '-чи', + 2: '-чи', + 3: '-чү', + 4: '-чү', + 5: '-чи', + 6: '-чы', + 7: '-чи', + 8: '-чи', + 9: '-чу', + 10: '-чу', + 20: '-чы', + 30: '-чу', + 40: '-чы', + 50: '-чү', + 60: '-чы', + 70: '-чи', + 80: '-чи', + 90: '-чу', + 100: '-чү' + }; + + var ky = moment.defineLocale('ky', { + months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + monthsShort : 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'), + weekdays : 'Жекшемби_Дүйшөмбү_Шейшемби_Шаршемби_Бейшемби_Жума_Ишемби'.split('_'), + weekdaysShort : 'Жек_Дүй_Шей_Шар_Бей_Жум_Ише'.split('_'), + weekdaysMin : 'Жк_Дй_Шй_Шр_Бй_Жм_Иш'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Бүгүн саат] LT', + nextDay : '[Эртең саат] LT', + nextWeek : 'dddd [саат] LT', + lastDay : '[Кече саат] LT', + lastWeek : '[Өткен аптанын] dddd [күнү] [саат] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ичинде', + past : '%s мурун', + s : 'бирнече секунд', + m : 'бир мүнөт', + mm : '%d мүнөт', + h : 'бир саат', + hh : '%d саат', + d : 'бир күн', + dd : '%d күн', + M : 'бир ай', + MM : '%d ай', + y : 'бир жыл', + yy : '%d жыл' + }, + ordinalParse: /\d{1,2}-(чи|чы|чү|чу)/, + ordinal : function (number) { + var a = number % 10, + b = number >= 100 ? 100 : null; + return number + (suffixes[number] || suffixes[a] || suffixes[b]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return ky; + +}));
@@ -0,0 +1,136 @@
+//! moment.js locale configuration +//! locale : Luxembourgish [lb] +//! author : mweimerskirch : https://github.com/mweimerskirch, David Raison : https://github.com/kwisatz + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eng Minutt', 'enger Minutt'], + 'h': ['eng Stonn', 'enger Stonn'], + 'd': ['een Dag', 'engem Dag'], + 'M': ['ee Mount', 'engem Mount'], + 'y': ['ee Joer', 'engem Joer'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; + } + function processFutureTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'a ' + string; + } + return 'an ' + string; + } + function processPastTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'viru ' + string; + } + return 'virun ' + string; + } + /** + * Returns true if the word before the given number loses the '-n' ending. + * e.g. 'an 10 Deeg' but 'a 5 Deeg' + * + * @param number {integer} + * @returns {boolean} + */ + function eifelerRegelAppliesToNumber(number) { + number = parseInt(number, 10); + if (isNaN(number)) { + return false; + } + if (number < 0) { + // Negative Number --> always true + return true; + } else if (number < 10) { + // Only 1 digit + if (4 <= number && number <= 7) { + return true; + } + return false; + } else if (number < 100) { + // 2 digits + var lastDigit = number % 10, firstDigit = number / 10; + if (lastDigit === 0) { + return eifelerRegelAppliesToNumber(firstDigit); + } + return eifelerRegelAppliesToNumber(lastDigit); + } else if (number < 10000) { + // 3 or 4 digits --> recursively check first digit + while (number >= 10) { + number = number / 10; + } + return eifelerRegelAppliesToNumber(number); + } else { + // Anything larger than 4 digits: recursively check first n-3 digits + number = number / 1000; + return eifelerRegelAppliesToNumber(number); + } + } + + var lb = moment.defineLocale('lb', { + months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + monthsParseExact : true, + weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'), + weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'), + weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm [Auer]', + LTS: 'H:mm:ss [Auer]', + L: 'DD.MM.YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm [Auer]', + LLLL: 'dddd, D. MMMM YYYY H:mm [Auer]' + }, + calendar: { + sameDay: '[Haut um] LT', + sameElse: 'L', + nextDay: '[Muer um] LT', + nextWeek: 'dddd [um] LT', + lastDay: '[Gëschter um] LT', + lastWeek: function () { + // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule + switch (this.day()) { + case 2: + case 4: + return '[Leschten] dddd [um] LT'; + default: + return '[Leschte] dddd [um] LT'; + } + } + }, + relativeTime : { + future : processFutureTime, + past : processPastTime, + s : 'e puer Sekonnen', + m : processRelativeTime, + mm : '%d Minutten', + h : processRelativeTime, + hh : '%d Stonnen', + d : processRelativeTime, + dd : '%d Deeg', + M : processRelativeTime, + MM : '%d Méint', + y : processRelativeTime, + yy : '%d Joer' + }, + ordinalParse: /\d{1,2}\./, + ordinal: '%d.', + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return lb; + +}));
@@ -0,0 +1,70 @@
+//! moment.js locale configuration +//! locale : Lao [lo] +//! author : Ryan Hart : https://github.com/ryanhart2 + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var lo = moment.defineLocale('lo', { + months : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'), + monthsShort : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'), + weekdays : 'ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'), + weekdaysShort : 'ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'), + weekdaysMin : 'ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'ວັນdddd D MMMM YYYY HH:mm' + }, + meridiemParse: /ຕອນເຊົ້າ|ຕອນແລງ/, + isPM: function (input) { + return input === 'ຕອນແລງ'; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ຕອນເຊົ້າ'; + } else { + return 'ຕອນແລງ'; + } + }, + calendar : { + sameDay : '[ມື້ນີ້ເວລາ] LT', + nextDay : '[ມື້ອື່ນເວລາ] LT', + nextWeek : '[ວັນ]dddd[ໜ້າເວລາ] LT', + lastDay : '[ມື້ວານນີ້ເວລາ] LT', + lastWeek : '[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'ອີກ %s', + past : '%sຜ່ານມາ', + s : 'ບໍ່ເທົ່າໃດວິນາທີ', + m : '1 ນາທີ', + mm : '%d ນາທີ', + h : '1 ຊົ່ວໂມງ', + hh : '%d ຊົ່ວໂມງ', + d : '1 ມື້', + dd : '%d ມື້', + M : '1 ເດືອນ', + MM : '%d ເດືອນ', + y : '1 ປີ', + yy : '%d ປີ' + }, + ordinalParse: /(ທີ່)\d{1,2}/, + ordinal : function (number) { + return 'ທີ່' + number; + } + }); + + return lo; + +}));
@@ -0,0 +1,117 @@
+//! moment.js locale configuration +//! locale : Lithuanian [lt] +//! author : Mindaugas Mozūras : https://github.com/mmozuras + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var units = { + 'm' : 'minutė_minutės_minutę', + 'mm': 'minutės_minučių_minutes', + 'h' : 'valanda_valandos_valandą', + 'hh': 'valandos_valandų_valandas', + 'd' : 'diena_dienos_dieną', + 'dd': 'dienos_dienų_dienas', + 'M' : 'mėnuo_mėnesio_mėnesį', + 'MM': 'mėnesiai_mėnesių_mėnesius', + 'y' : 'metai_metų_metus', + 'yy': 'metai_metų_metus' + }; + function translateSeconds(number, withoutSuffix, key, isFuture) { + if (withoutSuffix) { + return 'kelios sekundės'; + } else { + return isFuture ? 'kelių sekundžių' : 'kelias sekundes'; + } + } + function translateSingular(number, withoutSuffix, key, isFuture) { + return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]); + } + function special(number) { + return number % 10 === 0 || (number > 10 && number < 20); + } + function forms(key) { + return units[key].split('_'); + } + function translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + if (number === 1) { + return result + translateSingular(number, withoutSuffix, key[0], isFuture); + } else if (withoutSuffix) { + return result + (special(number) ? forms(key)[1] : forms(key)[0]); + } else { + if (isFuture) { + return result + forms(key)[1]; + } else { + return result + (special(number) ? forms(key)[1] : forms(key)[2]); + } + } + } + var lt = moment.defineLocale('lt', { + months : { + format: 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'), + standalone: 'sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis'.split('_'), + isFormat: /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?|MMMM?(\[[^\[\]]*\]|\s+)+D[oD]?/ + }, + monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'), + weekdays : { + format: 'sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį'.split('_'), + standalone: 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_'), + isFormat: /dddd HH:mm/ + }, + weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'), + weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'YYYY [m.] MMMM D [d.]', + LLL : 'YYYY [m.] MMMM D [d.], HH:mm [val.]', + LLLL : 'YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]', + l : 'YYYY-MM-DD', + ll : 'YYYY [m.] MMMM D [d.]', + lll : 'YYYY [m.] MMMM D [d.], HH:mm [val.]', + llll : 'YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]' + }, + calendar : { + sameDay : '[Šiandien] LT', + nextDay : '[Rytoj] LT', + nextWeek : 'dddd LT', + lastDay : '[Vakar] LT', + lastWeek : '[Praėjusį] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : 'po %s', + past : 'prieš %s', + s : translateSeconds, + m : translateSingular, + mm : translate, + h : translateSingular, + hh : translate, + d : translateSingular, + dd : translate, + M : translateSingular, + MM : translate, + y : translateSingular, + yy : translate + }, + ordinalParse: /\d{1,2}-oji/, + ordinal : function (number) { + return number + '-oji'; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return lt; + +}));
@@ -0,0 +1,97 @@
+//! moment.js locale configuration +//! locale : Latvian [lv] +//! author : Kristaps Karlsons : https://github.com/skakri +//! author : Jānis Elmeris : https://github.com/JanisE + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var units = { + 'm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'mm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'h': 'stundas_stundām_stunda_stundas'.split('_'), + 'hh': 'stundas_stundām_stunda_stundas'.split('_'), + 'd': 'dienas_dienām_diena_dienas'.split('_'), + 'dd': 'dienas_dienām_diena_dienas'.split('_'), + 'M': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'MM': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'y': 'gada_gadiem_gads_gadi'.split('_'), + 'yy': 'gada_gadiem_gads_gadi'.split('_') + }; + /** + * @param withoutSuffix boolean true = a length of time; false = before/after a period of time. + */ + function format(forms, number, withoutSuffix) { + if (withoutSuffix) { + // E.g. "21 minūte", "3 minūtes". + return number % 10 === 1 && number % 100 !== 11 ? forms[2] : forms[3]; + } else { + // E.g. "21 minūtes" as in "pēc 21 minūtes". + // E.g. "3 minūtēm" as in "pēc 3 minūtēm". + return number % 10 === 1 && number % 100 !== 11 ? forms[0] : forms[1]; + } + } + function relativeTimeWithPlural(number, withoutSuffix, key) { + return number + ' ' + format(units[key], number, withoutSuffix); + } + function relativeTimeWithSingular(number, withoutSuffix, key) { + return format(units[key], number, withoutSuffix); + } + function relativeSeconds(number, withoutSuffix) { + return withoutSuffix ? 'dažas sekundes' : 'dažām sekundēm'; + } + + var lv = moment.defineLocale('lv', { + months : 'janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec'.split('_'), + weekdays : 'svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena'.split('_'), + weekdaysShort : 'Sv_P_O_T_C_Pk_S'.split('_'), + weekdaysMin : 'Sv_P_O_T_C_Pk_S'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY.', + LL : 'YYYY. [gada] D. MMMM', + LLL : 'YYYY. [gada] D. MMMM, HH:mm', + LLLL : 'YYYY. [gada] D. MMMM, dddd, HH:mm' + }, + calendar : { + sameDay : '[Šodien pulksten] LT', + nextDay : '[Rīt pulksten] LT', + nextWeek : 'dddd [pulksten] LT', + lastDay : '[Vakar pulksten] LT', + lastWeek : '[Pagājušā] dddd [pulksten] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'pēc %s', + past : 'pirms %s', + s : relativeSeconds, + m : relativeTimeWithSingular, + mm : relativeTimeWithPlural, + h : relativeTimeWithSingular, + hh : relativeTimeWithPlural, + d : relativeTimeWithSingular, + dd : relativeTimeWithPlural, + M : relativeTimeWithSingular, + MM : relativeTimeWithPlural, + y : relativeTimeWithSingular, + yy : relativeTimeWithPlural + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return lv; + +}));
@@ -0,0 +1,111 @@
+//! moment.js locale configuration +//! locale : Montenegrin [me] +//! author : Miodrag Nikač <miodrag@restartit.me> : https://github.com/miodragnikac + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jednog minuta'], + mm: ['minut', 'minuta', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mjesec', 'mjeseca', 'mjeseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var me = moment.defineLocale('me', { + months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'), + monthsParseExact : true, + weekdays: 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort: 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm', + LTS : 'H:mm:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm', + LLLL: 'dddd, D. MMMM YYYY H:mm' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sjutra u] LT', + + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedjelje] [u] LT', + '[prošlog] [ponedjeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srijede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'nekoliko sekundi', + m : translator.translate, + mm : translator.translate, + h : translator.translate, + hh : translator.translate, + d : 'dan', + dd : translator.translate, + M : 'mjesec', + MM : translator.translate, + y : 'godinu', + yy : translator.translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return me; + +}));
@@ -0,0 +1,90 @@
+//! moment.js locale configuration +//! locale : Macedonian [mk] +//! author : Borislav Mickov : https://github.com/B0k0 + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var mk = moment.defineLocale('mk', { + months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'), + weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'), + weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'D.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd, D MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[Денес во] LT', + nextDay : '[Утре во] LT', + nextWeek : '[Во] dddd [во] LT', + lastDay : '[Вчера во] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + case 6: + return '[Изминатата] dddd [во] LT'; + case 1: + case 2: + case 4: + case 5: + return '[Изминатиот] dddd [во] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'после %s', + past : 'пред %s', + s : 'неколку секунди', + m : 'минута', + mm : '%d минути', + h : 'час', + hh : '%d часа', + d : 'ден', + dd : '%d дена', + M : 'месец', + MM : '%d месеци', + y : 'година', + yy : '%d години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + ordinal : function (number) { + var lastDigit = number % 10, + last2Digits = number % 100; + if (number === 0) { + return number + '-ев'; + } else if (last2Digits === 0) { + return number + '-ен'; + } else if (last2Digits > 10 && last2Digits < 20) { + return number + '-ти'; + } else if (lastDigit === 1) { + return number + '-ви'; + } else if (lastDigit === 2) { + return number + '-ри'; + } else if (lastDigit === 7 || lastDigit === 8) { + return number + '-ми'; + } else { + return number + '-ти'; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return mk; + +}));
@@ -0,0 +1,81 @@
+//! moment.js locale configuration +//! locale : Malayalam [ml] +//! author : Floyd Pink : https://github.com/floydpink + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ml = moment.defineLocale('ml', { + months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'), + monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'), + monthsParseExact : true, + weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'), + weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'), + weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'), + longDateFormat : { + LT : 'A h:mm -നു', + LTS : 'A h:mm:ss -നു', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm -നു', + LLLL : 'dddd, D MMMM YYYY, A h:mm -നു' + }, + calendar : { + sameDay : '[ഇന്ന്] LT', + nextDay : '[നാളെ] LT', + nextWeek : 'dddd, LT', + lastDay : '[ഇന്നലെ] LT', + lastWeek : '[കഴിഞ്ഞ] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s കഴിഞ്ഞ്', + past : '%s മുൻപ്', + s : 'അൽപ നിമിഷങ്ങൾ', + m : 'ഒരു മിനിറ്റ്', + mm : '%d മിനിറ്റ്', + h : 'ഒരു മണിക്കൂർ', + hh : '%d മണിക്കൂർ', + d : 'ഒരു ദിവസം', + dd : '%d ദിവസം', + M : 'ഒരു മാസം', + MM : '%d മാസം', + y : 'ഒരു വർഷം', + yy : '%d വർഷം' + }, + meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if ((meridiem === 'രാത്രി' && hour >= 4) || + meridiem === 'ഉച്ച കഴിഞ്ഞ്' || + meridiem === 'വൈകുന്നേരം') { + return hour + 12; + } else { + return hour; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'രാത്രി'; + } else if (hour < 12) { + return 'രാവിലെ'; + } else if (hour < 17) { + return 'ഉച്ച കഴിഞ്ഞ്'; + } else if (hour < 20) { + return 'വൈകുന്നേരം'; + } else { + return 'രാത്രി'; + } + } + }); + + return ml; + +}));
@@ -0,0 +1,159 @@
+//! moment.js locale configuration +//! locale : Marathi [mr] +//! author : Harshad Kale : https://github.com/kalehv +//! author : Vivek Athalye : https://github.com/vnathalye + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + function relativeTimeMr(number, withoutSuffix, string, isFuture) + { + var output = ''; + if (withoutSuffix) { + switch (string) { + case 's': output = 'काही सेकंद'; break; + case 'm': output = 'एक मिनिट'; break; + case 'mm': output = '%d मिनिटे'; break; + case 'h': output = 'एक तास'; break; + case 'hh': output = '%d तास'; break; + case 'd': output = 'एक दिवस'; break; + case 'dd': output = '%d दिवस'; break; + case 'M': output = 'एक महिना'; break; + case 'MM': output = '%d महिने'; break; + case 'y': output = 'एक वर्ष'; break; + case 'yy': output = '%d वर्षे'; break; + } + } + else { + switch (string) { + case 's': output = 'काही सेकंदां'; break; + case 'm': output = 'एका मिनिटा'; break; + case 'mm': output = '%d मिनिटां'; break; + case 'h': output = 'एका तासा'; break; + case 'hh': output = '%d तासां'; break; + case 'd': output = 'एका दिवसा'; break; + case 'dd': output = '%d दिवसां'; break; + case 'M': output = 'एका महिन्या'; break; + case 'MM': output = '%d महिन्यां'; break; + case 'y': output = 'एका वर्षा'; break; + case 'yy': output = '%d वर्षां'; break; + } + } + return output.replace(/%d/i, number); + } + + var mr = moment.defineLocale('mr', { + months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'), + monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'), + monthsParseExact : true, + weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm वाजता', + LTS : 'A h:mm:ss वाजता', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm वाजता', + LLLL : 'dddd, D MMMM YYYY, A h:mm वाजता' + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[उद्या] LT', + nextWeek : 'dddd, LT', + lastDay : '[काल] LT', + lastWeek: '[मागील] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future: '%sमध्ये', + past: '%sपूर्वी', + s: relativeTimeMr, + m: relativeTimeMr, + mm: relativeTimeMr, + h: relativeTimeMr, + hh: relativeTimeMr, + d: relativeTimeMr, + dd: relativeTimeMr, + M: relativeTimeMr, + MM: relativeTimeMr, + y: relativeTimeMr, + yy: relativeTimeMr + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + meridiemParse: /रात्री|सकाळी|दुपारी|सायंकाळी/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात्री') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सकाळी') { + return hour; + } else if (meridiem === 'दुपारी') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'सायंकाळी') { + return hour + 12; + } + }, + meridiem: function (hour, minute, isLower) { + if (hour < 4) { + return 'रात्री'; + } else if (hour < 10) { + return 'सकाळी'; + } else if (hour < 17) { + return 'दुपारी'; + } else if (hour < 20) { + return 'सायंकाळी'; + } else { + return 'रात्री'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + return mr; + +}));
@@ -0,0 +1,83 @@
+//! moment.js locale configuration +//! locale : Malay [ms-my] +//! note : DEPRECATED, the correct one is [ms] +//! author : Weldan Jamili : https://github.com/weldan + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ms_my = moment.defineLocale('ms-my', { + months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'), + monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'), + weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'), + weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'), + weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /pagi|tengahari|petang|malam/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'tengahari') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'petang' || meridiem === 'malam') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'tengahari'; + } else if (hours < 19) { + return 'petang'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Esok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kelmarin pukul] LT', + lastWeek : 'dddd [lepas pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'dalam %s', + past : '%s yang lepas', + s : 'beberapa saat', + m : 'seminit', + mm : '%d minit', + h : 'sejam', + hh : '%d jam', + d : 'sehari', + dd : '%d hari', + M : 'sebulan', + MM : '%d bulan', + y : 'setahun', + yy : '%d tahun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return ms_my; + +}));
@@ -0,0 +1,82 @@
+//! moment.js locale configuration +//! locale : Malay [ms] +//! author : Weldan Jamili : https://github.com/weldan + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ms = moment.defineLocale('ms', { + months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'), + monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'), + weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'), + weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'), + weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /pagi|tengahari|petang|malam/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'tengahari') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'petang' || meridiem === 'malam') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'tengahari'; + } else if (hours < 19) { + return 'petang'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Esok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kelmarin pukul] LT', + lastWeek : 'dddd [lepas pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'dalam %s', + past : '%s yang lepas', + s : 'beberapa saat', + m : 'seminit', + mm : '%d minit', + h : 'sejam', + hh : '%d jam', + d : 'sehari', + dd : '%d hari', + M : 'sebulan', + MM : '%d bulan', + y : 'setahun', + yy : '%d tahun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return ms; + +}));
@@ -0,0 +1,93 @@
+//! moment.js locale configuration +//! locale : Burmese [my] +//! author : Squar team, mysquar.com + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '၁', + '2': '၂', + '3': '၃', + '4': '၄', + '5': '၅', + '6': '၆', + '7': '၇', + '8': '၈', + '9': '၉', + '0': '၀' + }, numberMap = { + '၁': '1', + '၂': '2', + '၃': '3', + '၄': '4', + '၅': '5', + '၆': '6', + '၇': '7', + '၈': '8', + '၉': '9', + '၀': '0' + }; + + var my = moment.defineLocale('my', { + months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'), + monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'), + weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'), + weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + + longDateFormat: { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[ယနေ.] LT [မှာ]', + nextDay: '[မနက်ဖြန်] LT [မှာ]', + nextWeek: 'dddd LT [မှာ]', + lastDay: '[မနေ.က] LT [မှာ]', + lastWeek: '[ပြီးခဲ့သော] dddd LT [မှာ]', + sameElse: 'L' + }, + relativeTime: { + future: 'လာမည့် %s မှာ', + past: 'လွန်ခဲ့သော %s က', + s: 'စက္ကန်.အနည်းငယ်', + m: 'တစ်မိနစ်', + mm: '%d မိနစ်', + h: 'တစ်နာရီ', + hh: '%d နာရီ', + d: 'တစ်ရက်', + dd: '%d ရက်', + M: 'တစ်လ', + MM: '%d လ', + y: 'တစ်နှစ်', + yy: '%d နှစ်' + }, + preparse: function (string) { + return string.replace(/[၁၂၃၄၅၆၇၈၉၀]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 1st is the first week of the year. + } + }); + + return my; + +}));
@@ -0,0 +1,63 @@
+//! moment.js locale configuration +//! locale : Norwegian Bokmål [nb] +//! authors : Espen Hovlandsdal : https://github.com/rexxars +//! Sigurd Gartmann : https://github.com/sigurdga + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var nb = moment.defineLocale('nb', { + months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.'.split('_'), + monthsParseExact : true, + weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'), + weekdaysShort : 'sø._ma._ti._on._to._fr._lø.'.split('_'), + weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] HH:mm', + LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm' + }, + calendar : { + sameDay: '[i dag kl.] LT', + nextDay: '[i morgen kl.] LT', + nextWeek: 'dddd [kl.] LT', + lastDay: '[i går kl.] LT', + lastWeek: '[forrige] dddd [kl.] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : '%s siden', + s : 'noen sekunder', + m : 'ett minutt', + mm : '%d minutter', + h : 'en time', + hh : '%d timer', + d : 'en dag', + dd : '%d dager', + M : 'en måned', + MM : '%d måneder', + y : 'ett år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return nb; + +}));
@@ -0,0 +1,123 @@
+//! moment.js locale configuration +//! locale : Nepalese [ne] +//! author : suvash : https://github.com/suvash + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var ne = moment.defineLocale('ne', { + months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'), + monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'), + monthsParseExact : true, + weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'), + weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'), + weekdaysMin : 'आ._सो._मं._बु._बि._शु._श.'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'Aको h:mm बजे', + LTS : 'Aको h:mm:ss बजे', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, Aको h:mm बजे', + LLLL : 'dddd, D MMMM YYYY, Aको h:mm बजे' + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + meridiemParse: /राति|बिहान|दिउँसो|साँझ/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'राति') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'बिहान') { + return hour; + } else if (meridiem === 'दिउँसो') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'साँझ') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 3) { + return 'राति'; + } else if (hour < 12) { + return 'बिहान'; + } else if (hour < 16) { + return 'दिउँसो'; + } else if (hour < 20) { + return 'साँझ'; + } else { + return 'राति'; + } + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[भोलि] LT', + nextWeek : '[आउँदो] dddd[,] LT', + lastDay : '[हिजो] LT', + lastWeek : '[गएको] dddd[,] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%sमा', + past : '%s अगाडि', + s : 'केही क्षण', + m : 'एक मिनेट', + mm : '%d मिनेट', + h : 'एक घण्टा', + hh : '%d घण्टा', + d : 'एक दिन', + dd : '%d दिन', + M : 'एक महिना', + MM : '%d महिना', + y : 'एक बर्ष', + yy : '%d बर्ष' + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + return ne; + +}));
@@ -0,0 +1,73 @@
+//! moment.js locale configuration +//! locale : Dutch [nl] +//! author : Joris Röling : https://github.com/jjupiter + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_'), + monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_'); + + var nl = moment.defineLocale('nl', { + months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShortWithoutDots[m.month()]; + } else { + return monthsShortWithDots[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'), + weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'), + weekdaysMin : 'Zo_Ma_Di_Wo_Do_Vr_Za'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[vandaag om] LT', + nextDay: '[morgen om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[gisteren om] LT', + lastWeek: '[afgelopen] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'over %s', + past : '%s geleden', + s : 'een paar seconden', + m : 'één minuut', + mm : '%d minuten', + h : 'één uur', + hh : '%d uur', + d : 'één dag', + dd : '%d dagen', + M : 'één maand', + MM : '%d maanden', + y : 'één jaar', + yy : '%d jaar' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return nl; + +}));
@@ -0,0 +1,60 @@
+//! moment.js locale configuration +//! locale : Nynorsk [nn] +//! author : https://github.com/mechuwind + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var nn = moment.defineLocale('nn', { + months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), + weekdays : 'sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag'.split('_'), + weekdaysShort : 'sun_mån_tys_ons_tor_fre_lau'.split('_'), + weekdaysMin : 'su_må_ty_on_to_fr_lø'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] H:mm', + LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm' + }, + calendar : { + sameDay: '[I dag klokka] LT', + nextDay: '[I morgon klokka] LT', + nextWeek: 'dddd [klokka] LT', + lastDay: '[I går klokka] LT', + lastWeek: '[Føregåande] dddd [klokka] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : '%s sidan', + s : 'nokre sekund', + m : 'eit minutt', + mm : '%d minutt', + h : 'ein time', + hh : '%d timar', + d : 'ein dag', + dd : '%d dagar', + M : 'ein månad', + MM : '%d månader', + y : 'eit år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return nn; + +}));
@@ -0,0 +1,124 @@
+//! moment.js locale configuration +//! locale : Punjabi (India) [pa-in] +//! author : Harpreet Singh : https://github.com/harpreetkhalsagtbit + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '੧', + '2': '੨', + '3': '੩', + '4': '੪', + '5': '੫', + '6': '੬', + '7': '੭', + '8': '੮', + '9': '੯', + '0': '੦' + }, + numberMap = { + '੧': '1', + '੨': '2', + '੩': '3', + '੪': '4', + '੫': '5', + '੬': '6', + '੭': '7', + '੮': '8', + '੯': '9', + '੦': '0' + }; + + var pa_in = moment.defineLocale('pa-in', { + // There are months name as per Nanakshahi Calender but they are not used as rigidly in modern Punjabi. + months : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'), + monthsShort : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'), + weekdays : 'ਐਤਵਾਰ_ਸੋਮਵਾਰ_ਮੰਗਲਵਾਰ_ਬੁਧਵਾਰ_ਵੀਰਵਾਰ_ਸ਼ੁੱਕਰਵਾਰ_ਸ਼ਨੀਚਰਵਾਰ'.split('_'), + weekdaysShort : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'), + weekdaysMin : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'), + longDateFormat : { + LT : 'A h:mm ਵਜੇ', + LTS : 'A h:mm:ss ਵਜੇ', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm ਵਜੇ', + LLLL : 'dddd, D MMMM YYYY, A h:mm ਵਜੇ' + }, + calendar : { + sameDay : '[ਅਜ] LT', + nextDay : '[ਕਲ] LT', + nextWeek : 'dddd, LT', + lastDay : '[ਕਲ] LT', + lastWeek : '[ਪਿਛਲੇ] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ਵਿੱਚ', + past : '%s ਪਿਛਲੇ', + s : 'ਕੁਝ ਸਕਿੰਟ', + m : 'ਇਕ ਮਿੰਟ', + mm : '%d ਮਿੰਟ', + h : 'ਇੱਕ ਘੰਟਾ', + hh : '%d ਘੰਟੇ', + d : 'ਇੱਕ ਦਿਨ', + dd : '%d ਦਿਨ', + M : 'ਇੱਕ ਮਹੀਨਾ', + MM : '%d ਮਹੀਨੇ', + y : 'ਇੱਕ ਸਾਲ', + yy : '%d ਸਾਲ' + }, + preparse: function (string) { + return string.replace(/[੧੨੩੪੫੬੭੮੯੦]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + // Punjabi notation for meridiems are quite fuzzy in practice. While there exists + // a rigid notion of a 'Pahar' it is not used as rigidly in modern Punjabi. + meridiemParse: /ਰਾਤ|ਸਵੇਰ|ਦੁਪਹਿਰ|ਸ਼ਾਮ/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'ਰਾਤ') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'ਸਵੇਰ') { + return hour; + } else if (meridiem === 'ਦੁਪਹਿਰ') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'ਸ਼ਾਮ') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ਰਾਤ'; + } else if (hour < 10) { + return 'ਸਵੇਰ'; + } else if (hour < 17) { + return 'ਦੁਪਹਿਰ'; + } else if (hour < 20) { + return 'ਸ਼ਾਮ'; + } else { + return 'ਰਾਤ'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + return pa_in; + +}));
@@ -0,0 +1,105 @@
+//! moment.js locale configuration +//! locale : Polish [pl] +//! author : Rafal Hirsz : https://github.com/evoL + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split('_'), + monthsSubjective = 'stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia'.split('_'); + function plural(n) { + return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1); + } + function translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'minuta' : 'minutę'; + case 'mm': + return result + (plural(number) ? 'minuty' : 'minut'); + case 'h': + return withoutSuffix ? 'godzina' : 'godzinę'; + case 'hh': + return result + (plural(number) ? 'godziny' : 'godzin'); + case 'MM': + return result + (plural(number) ? 'miesiące' : 'miesięcy'); + case 'yy': + return result + (plural(number) ? 'lata' : 'lat'); + } + } + + var pl = moment.defineLocale('pl', { + months : function (momentToFormat, format) { + if (format === '') { + // Hack: if format empty we know this is used to generate + // RegExp by moment. Give then back both valid forms of months + // in RegExp ready format. + return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')'; + } else if (/D MMMM/.test(format)) { + return monthsSubjective[momentToFormat.month()]; + } else { + return monthsNominative[momentToFormat.month()]; + } + }, + monthsShort : 'sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru'.split('_'), + weekdays : 'niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota'.split('_'), + weekdaysShort : 'nie_pon_wt_śr_czw_pt_sb'.split('_'), + weekdaysMin : 'Nd_Pn_Wt_Śr_Cz_Pt_So'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Dziś o] LT', + nextDay: '[Jutro o] LT', + nextWeek: '[W] dddd [o] LT', + lastDay: '[Wczoraj o] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[W zeszłą niedzielę o] LT'; + case 3: + return '[W zeszłą środę o] LT'; + case 6: + return '[W zeszłą sobotę o] LT'; + default: + return '[W zeszły] dddd [o] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'za %s', + past : '%s temu', + s : 'kilka sekund', + m : translate, + mm : translate, + h : translate, + hh : translate, + d : '1 dzień', + dd : '%d dni', + M : 'miesiąc', + MM : translate, + y : 'rok', + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return pl; + +}));
@@ -0,0 +1,61 @@
+//! moment.js locale configuration +//! locale : Portuguese (Brazil) [pt-br] +//! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var pt_br = moment.defineLocale('pt-br', { + months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'), + monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'), + weekdays : 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split('_'), + weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'), + weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY [às] HH:mm', + LLLL : 'dddd, D [de] MMMM [de] YYYY [às] HH:mm' + }, + calendar : { + sameDay: '[Hoje às] LT', + nextDay: '[Amanhã às] LT', + nextWeek: 'dddd [às] LT', + lastDay: '[Ontem às] LT', + lastWeek: function () { + return (this.day() === 0 || this.day() === 6) ? + '[Último] dddd [às] LT' : // Saturday + Sunday + '[Última] dddd [às] LT'; // Monday - Friday + }, + sameElse: 'L' + }, + relativeTime : { + future : 'em %s', + past : '%s atrás', + s : 'poucos segundos', + m : 'um minuto', + mm : '%d minutos', + h : 'uma hora', + hh : '%d horas', + d : 'um dia', + dd : '%d dias', + M : 'um mês', + MM : '%d meses', + y : 'um ano', + yy : '%d anos' + }, + ordinalParse: /\d{1,2}º/, + ordinal : '%dº' + }); + + return pt_br; + +}));
@@ -0,0 +1,65 @@
+//! moment.js locale configuration +//! locale : Portuguese [pt] +//! author : Jefferson : https://github.com/jalex79 + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var pt = moment.defineLocale('pt', { + months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'), + monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'), + weekdays : 'Domingo_Segunda-Feira_Terça-Feira_Quarta-Feira_Quinta-Feira_Sexta-Feira_Sábado'.split('_'), + weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'), + weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY HH:mm', + LLLL : 'dddd, D [de] MMMM [de] YYYY HH:mm' + }, + calendar : { + sameDay: '[Hoje às] LT', + nextDay: '[Amanhã às] LT', + nextWeek: 'dddd [às] LT', + lastDay: '[Ontem às] LT', + lastWeek: function () { + return (this.day() === 0 || this.day() === 6) ? + '[Último] dddd [às] LT' : // Saturday + Sunday + '[Última] dddd [às] LT'; // Monday - Friday + }, + sameElse: 'L' + }, + relativeTime : { + future : 'em %s', + past : 'há %s', + s : 'segundos', + m : 'um minuto', + mm : '%d minutos', + h : 'uma hora', + hh : '%d horas', + d : 'um dia', + dd : '%d dias', + M : 'um mês', + MM : '%d meses', + y : 'um ano', + yy : '%d anos' + }, + ordinalParse: /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return pt; + +}));
@@ -0,0 +1,75 @@
+//! moment.js locale configuration +//! locale : Romanian [ro] +//! author : Vlad Gurdiga : https://github.com/gurdiga +//! author : Valentin Agachi : https://github.com/avaly + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': 'minute', + 'hh': 'ore', + 'dd': 'zile', + 'MM': 'luni', + 'yy': 'ani' + }, + separator = ' '; + if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) { + separator = ' de '; + } + return number + separator + format[key]; + } + + var ro = moment.defineLocale('ro', { + months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'), + monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays : 'duminică_luni_marți_miercuri_joi_vineri_sâmbătă'.split('_'), + weekdaysShort : 'Dum_Lun_Mar_Mie_Joi_Vin_Sâm'.split('_'), + weekdaysMin : 'Du_Lu_Ma_Mi_Jo_Vi_Sâ'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd, D MMMM YYYY H:mm' + }, + calendar : { + sameDay: '[azi la] LT', + nextDay: '[mâine la] LT', + nextWeek: 'dddd [la] LT', + lastDay: '[ieri la] LT', + lastWeek: '[fosta] dddd [la] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'peste %s', + past : '%s în urmă', + s : 'câteva secunde', + m : 'un minut', + mm : relativeTimeWithPlural, + h : 'o oră', + hh : relativeTimeWithPlural, + d : 'o zi', + dd : relativeTimeWithPlural, + M : 'o lună', + MM : relativeTimeWithPlural, + y : 'un an', + yy : relativeTimeWithPlural + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return ro; + +}));
@@ -0,0 +1,183 @@
+//! moment.js locale configuration +//! locale : Russian [ru] +//! author : Viktorminator : https://github.com/Viktorminator +//! Author : Menelion Elensúle : https://github.com/Oire +//! author : Коренберг Марк : https://github.com/socketpair + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); + } + function relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут', + 'hh': 'час_часа_часов', + 'dd': 'день_дня_дней', + 'MM': 'месяц_месяца_месяцев', + 'yy': 'год_года_лет' + }; + if (key === 'm') { + return withoutSuffix ? 'минута' : 'минуту'; + } + else { + return number + ' ' + plural(format[key], +number); + } + } + var monthsParse = [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[йя]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i]; + + // http://new.gramota.ru/spravka/rules/139-prop : § 103 + // Сокращения месяцев: http://new.gramota.ru/spravka/buro/search-answer?s=242637 + // CLDR data: http://www.unicode.org/cldr/charts/28/summary/ru.html#1753 + var ru = moment.defineLocale('ru', { + months : { + format: 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_'), + standalone: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_') + }, + monthsShort : { + // по CLDR именно "июл." и "июн.", но какой смысл менять букву на точку ? + format: 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split('_'), + standalone: 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split('_') + }, + weekdays : { + standalone: 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'), + format: 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_'), + isFormat: /\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/ + }, + weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + monthsParse : monthsParse, + longMonthsParse : monthsParse, + shortMonthsParse : monthsParse, + + // полные названия с падежами, по три буквы, для некоторых, по 4 буквы, сокращения с точкой и без точки + monthsRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i, + + // копия предыдущего + monthsShortRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i, + + // полные названия с падежами + monthsStrictRegex: /^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i, + + // Выражение, которое соотвествует только сокращённым формам + monthsShortStrictRegex: /^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY г.', + LLL : 'D MMMM YYYY г., HH:mm', + LLLL : 'dddd, D MMMM YYYY г., HH:mm' + }, + calendar : { + sameDay: '[Сегодня в] LT', + nextDay: '[Завтра в] LT', + lastDay: '[Вчера в] LT', + nextWeek: function (now) { + if (now.week() !== this.week()) { + switch (this.day()) { + case 0: + return '[В следующее] dddd [в] LT'; + case 1: + case 2: + case 4: + return '[В следующий] dddd [в] LT'; + case 3: + case 5: + case 6: + return '[В следующую] dddd [в] LT'; + } + } else { + if (this.day() === 2) { + return '[Во] dddd [в] LT'; + } else { + return '[В] dddd [в] LT'; + } + } + }, + lastWeek: function (now) { + if (now.week() !== this.week()) { + switch (this.day()) { + case 0: + return '[В прошлое] dddd [в] LT'; + case 1: + case 2: + case 4: + return '[В прошлый] dddd [в] LT'; + case 3: + case 5: + case 6: + return '[В прошлую] dddd [в] LT'; + } + } else { + if (this.day() === 2) { + return '[Во] dddd [в] LT'; + } else { + return '[В] dddd [в] LT'; + } + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'через %s', + past : '%s назад', + s : 'несколько секунд', + m : relativeTimeWithPlural, + mm : relativeTimeWithPlural, + h : 'час', + hh : relativeTimeWithPlural, + d : 'день', + dd : relativeTimeWithPlural, + M : 'месяц', + MM : relativeTimeWithPlural, + y : 'год', + yy : relativeTimeWithPlural + }, + meridiemParse: /ночи|утра|дня|вечера/i, + isPM : function (input) { + return /^(дня|вечера)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночи'; + } else if (hour < 12) { + return 'утра'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечера'; + } + }, + ordinalParse: /\d{1,2}-(й|го|я)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + return number + '-й'; + case 'D': + return number + '-го'; + case 'w': + case 'W': + return number + '-я'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return ru; + +}));
@@ -0,0 +1,61 @@
+//! moment.js locale configuration +//! locale : Northern Sami [se] +//! authors : Bård Rolstad Henriksen : https://github.com/karamell + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + + var se = moment.defineLocale('se', { + months : 'ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu'.split('_'), + monthsShort : 'ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov'.split('_'), + weekdays : 'sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat'.split('_'), + weekdaysShort : 'sotn_vuos_maŋ_gask_duor_bear_láv'.split('_'), + weekdaysMin : 's_v_m_g_d_b_L'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'MMMM D. [b.] YYYY', + LLL : 'MMMM D. [b.] YYYY [ti.] HH:mm', + LLLL : 'dddd, MMMM D. [b.] YYYY [ti.] HH:mm' + }, + calendar : { + sameDay: '[otne ti] LT', + nextDay: '[ihttin ti] LT', + nextWeek: 'dddd [ti] LT', + lastDay: '[ikte ti] LT', + lastWeek: '[ovddit] dddd [ti] LT', + sameElse: 'L' + }, + relativeTime : { + future : '%s geažes', + past : 'maŋit %s', + s : 'moadde sekunddat', + m : 'okta minuhta', + mm : '%d minuhtat', + h : 'okta diimmu', + hh : '%d diimmut', + d : 'okta beaivi', + dd : '%d beaivvit', + M : 'okta mánnu', + MM : '%d mánut', + y : 'okta jahki', + yy : '%d jagit' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return se; + +}));
@@ -0,0 +1,71 @@
+//! moment.js locale configuration +//! locale : Sinhalese [si] +//! author : Sampath Sitinamaluwa : https://github.com/sampathsris + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + /*jshint -W100*/ + var si = moment.defineLocale('si', { + months : 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split('_'), + monthsShort : 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split('_'), + weekdays : 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split('_'), + weekdaysShort : 'ඉරි_සඳු_අඟ_බදා_බ්රහ_සිකු_සෙන'.split('_'), + weekdaysMin : 'ඉ_ස_අ_බ_බ්ර_සි_සෙ'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'a h:mm', + LTS : 'a h:mm:ss', + L : 'YYYY/MM/DD', + LL : 'YYYY MMMM D', + LLL : 'YYYY MMMM D, a h:mm', + LLLL : 'YYYY MMMM D [වැනි] dddd, a h:mm:ss' + }, + calendar : { + sameDay : '[අද] LT[ට]', + nextDay : '[හෙට] LT[ට]', + nextWeek : 'dddd LT[ට]', + lastDay : '[ඊයේ] LT[ට]', + lastWeek : '[පසුගිය] dddd LT[ට]', + sameElse : 'L' + }, + relativeTime : { + future : '%sකින්', + past : '%sකට පෙර', + s : 'තත්පර කිහිපය', + m : 'මිනිත්තුව', + mm : 'මිනිත්තු %d', + h : 'පැය', + hh : 'පැය %d', + d : 'දිනය', + dd : 'දින %d', + M : 'මාසය', + MM : 'මාස %d', + y : 'වසර', + yy : 'වසර %d' + }, + ordinalParse: /\d{1,2} වැනි/, + ordinal : function (number) { + return number + ' වැනි'; + }, + meridiemParse : /පෙර වරු|පස් වරු|පෙ.ව|ප.ව./, + isPM : function (input) { + return input === 'ප.ව.' || input === 'පස් වරු'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'ප.ව.' : 'පස් වරු'; + } else { + return isLower ? 'පෙ.ව.' : 'පෙර වරු'; + } + } + }); + + return si; + +}));
@@ -0,0 +1,150 @@
+//! moment.js locale configuration +//! locale : Slovak [sk] +//! author : Martin Minka : https://github.com/k2s +//! based on work of petrbela : https://github.com/petrbela + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var months = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_'), + monthsShort = 'jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec'.split('_'); + function plural(n) { + return (n > 1) && (n < 5); + } + function translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': // a few seconds / in a few seconds / a few seconds ago + return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami'; + case 'm': // a minute / in a minute / a minute ago + return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou'); + case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'minúty' : 'minút'); + } else { + return result + 'minútami'; + } + break; + case 'h': // an hour / in an hour / an hour ago + return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou'); + case 'hh': // 9 hours / in 9 hours / 9 hours ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'hodiny' : 'hodín'); + } else { + return result + 'hodinami'; + } + break; + case 'd': // a day / in a day / a day ago + return (withoutSuffix || isFuture) ? 'deň' : 'dňom'; + case 'dd': // 9 days / in 9 days / 9 days ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'dni' : 'dní'); + } else { + return result + 'dňami'; + } + break; + case 'M': // a month / in a month / a month ago + return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom'; + case 'MM': // 9 months / in 9 months / 9 months ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'mesiace' : 'mesiacov'); + } else { + return result + 'mesiacmi'; + } + break; + case 'y': // a year / in a year / a year ago + return (withoutSuffix || isFuture) ? 'rok' : 'rokom'; + case 'yy': // 9 years / in 9 years / 9 years ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'roky' : 'rokov'); + } else { + return result + 'rokmi'; + } + break; + } + } + + var sk = moment.defineLocale('sk', { + months : months, + monthsShort : monthsShort, + weekdays : 'nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota'.split('_'), + weekdaysShort : 'ne_po_ut_st_št_pi_so'.split('_'), + weekdaysMin : 'ne_po_ut_st_št_pi_so'.split('_'), + longDateFormat : { + LT: 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd D. MMMM YYYY H:mm' + }, + calendar : { + sameDay: '[dnes o] LT', + nextDay: '[zajtra o] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[v nedeľu o] LT'; + case 1: + case 2: + return '[v] dddd [o] LT'; + case 3: + return '[v stredu o] LT'; + case 4: + return '[vo štvrtok o] LT'; + case 5: + return '[v piatok o] LT'; + case 6: + return '[v sobotu o] LT'; + } + }, + lastDay: '[včera o] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[minulú nedeľu o] LT'; + case 1: + case 2: + return '[minulý] dddd [o] LT'; + case 3: + return '[minulú stredu o] LT'; + case 4: + case 5: + return '[minulý] dddd [o] LT'; + case 6: + return '[minulú sobotu o] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'za %s', + past : 'pred %s', + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return sk; + +}));
@@ -0,0 +1,162 @@
+//! moment.js locale configuration +//! locale : Slovenian [sl] +//! author : Robert Sedovšek : https://github.com/sedovsek + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function processRelativeTime(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nekaj sekund' : 'nekaj sekundami'; + case 'm': + return withoutSuffix ? 'ena minuta' : 'eno minuto'; + case 'mm': + if (number === 1) { + result += withoutSuffix ? 'minuta' : 'minuto'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'minuti' : 'minutama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'minute' : 'minutami'; + } else { + result += withoutSuffix || isFuture ? 'minut' : 'minutami'; + } + return result; + case 'h': + return withoutSuffix ? 'ena ura' : 'eno uro'; + case 'hh': + if (number === 1) { + result += withoutSuffix ? 'ura' : 'uro'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'uri' : 'urama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'ure' : 'urami'; + } else { + result += withoutSuffix || isFuture ? 'ur' : 'urami'; + } + return result; + case 'd': + return withoutSuffix || isFuture ? 'en dan' : 'enim dnem'; + case 'dd': + if (number === 1) { + result += withoutSuffix || isFuture ? 'dan' : 'dnem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'dni' : 'dnevoma'; + } else { + result += withoutSuffix || isFuture ? 'dni' : 'dnevi'; + } + return result; + case 'M': + return withoutSuffix || isFuture ? 'en mesec' : 'enim mesecem'; + case 'MM': + if (number === 1) { + result += withoutSuffix || isFuture ? 'mesec' : 'mesecem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'meseca' : 'mesecema'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'mesece' : 'meseci'; + } else { + result += withoutSuffix || isFuture ? 'mesecev' : 'meseci'; + } + return result; + case 'y': + return withoutSuffix || isFuture ? 'eno leto' : 'enim letom'; + case 'yy': + if (number === 1) { + result += withoutSuffix || isFuture ? 'leto' : 'letom'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'leti' : 'letoma'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'leta' : 'leti'; + } else { + result += withoutSuffix || isFuture ? 'let' : 'leti'; + } + return result; + } + } + + var sl = moment.defineLocale('sl', { + months : 'januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december'.split('_'), + monthsShort : 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays : 'nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota'.split('_'), + weekdaysShort : 'ned._pon._tor._sre._čet._pet._sob.'.split('_'), + weekdaysMin : 'ne_po_to_sr_če_pe_so'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[danes ob] LT', + nextDay : '[jutri ob] LT', + + nextWeek : function () { + switch (this.day()) { + case 0: + return '[v] [nedeljo] [ob] LT'; + case 3: + return '[v] [sredo] [ob] LT'; + case 6: + return '[v] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[v] dddd [ob] LT'; + } + }, + lastDay : '[včeraj ob] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + return '[prejšnjo] [nedeljo] [ob] LT'; + case 3: + return '[prejšnjo] [sredo] [ob] LT'; + case 6: + return '[prejšnjo] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prejšnji] dddd [ob] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'čez %s', + past : 'pred %s', + s : processRelativeTime, + m : processRelativeTime, + mm : processRelativeTime, + h : processRelativeTime, + hh : processRelativeTime, + d : processRelativeTime, + dd : processRelativeTime, + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return sl; + +}));
@@ -0,0 +1,70 @@
+//! moment.js locale configuration +//! locale : Albanian [sq] +//! author : Flakërim Ismani : https://github.com/flakerimi +//! author: Menelion Elensúle: https://github.com/Oire (tests) +//! author : Oerd Cukalla : https://github.com/oerd (fixes) + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var sq = moment.defineLocale('sq', { + months : 'Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor'.split('_'), + monthsShort : 'Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj'.split('_'), + weekdays : 'E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë'.split('_'), + weekdaysShort : 'Die_Hën_Mar_Mër_Enj_Pre_Sht'.split('_'), + weekdaysMin : 'D_H_Ma_Më_E_P_Sh'.split('_'), + weekdaysParseExact : true, + meridiemParse: /PD|MD/, + isPM: function (input) { + return input.charAt(0) === 'M'; + }, + meridiem : function (hours, minutes, isLower) { + return hours < 12 ? 'PD' : 'MD'; + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Sot në] LT', + nextDay : '[Nesër në] LT', + nextWeek : 'dddd [në] LT', + lastDay : '[Dje në] LT', + lastWeek : 'dddd [e kaluar në] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'në %s', + past : '%s më parë', + s : 'disa sekonda', + m : 'një minutë', + mm : '%d minuta', + h : 'një orë', + hh : '%d orë', + d : 'një ditë', + dd : '%d ditë', + M : 'një muaj', + MM : '%d muaj', + y : 'një vit', + yy : '%d vite' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return sq; + +}));
@@ -0,0 +1,110 @@
+//! moment.js locale configuration +//! locale : Serbian Cyrillic [sr-cyrl] +//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var translator = { + words: { //Different grammatical cases + m: ['један минут', 'једне минуте'], + mm: ['минут', 'минуте', 'минута'], + h: ['један сат', 'једног сата'], + hh: ['сат', 'сата', 'сати'], + dd: ['дан', 'дана', 'дана'], + MM: ['месец', 'месеца', 'месеци'], + yy: ['година', 'године', 'година'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var sr_cyrl = moment.defineLocale('sr-cyrl', { + months: 'јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар'.split('_'), + monthsShort: 'јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.'.split('_'), + monthsParseExact: true, + weekdays: 'недеља_понедељак_уторак_среда_четвртак_петак_субота'.split('_'), + weekdaysShort: 'нед._пон._уто._сре._чет._пет._суб.'.split('_'), + weekdaysMin: 'не_по_ут_ср_че_пе_су'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm', + LTS : 'H:mm:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm', + LLLL: 'dddd, D. MMMM YYYY H:mm' + }, + calendar: { + sameDay: '[данас у] LT', + nextDay: '[сутра у] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[у] [недељу] [у] LT'; + case 3: + return '[у] [среду] [у] LT'; + case 6: + return '[у] [суботу] [у] LT'; + case 1: + case 2: + case 4: + case 5: + return '[у] dddd [у] LT'; + } + }, + lastDay : '[јуче у] LT', + lastWeek : function () { + var lastWeekDays = [ + '[прошле] [недеље] [у] LT', + '[прошлог] [понедељка] [у] LT', + '[прошлог] [уторка] [у] LT', + '[прошле] [среде] [у] LT', + '[прошлог] [четвртка] [у] LT', + '[прошлог] [петка] [у] LT', + '[прошле] [суботе] [у] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'за %s', + past : 'пре %s', + s : 'неколико секунди', + m : translator.translate, + mm : translator.translate, + h : translator.translate, + hh : translator.translate, + d : 'дан', + dd : translator.translate, + M : 'месец', + MM : translator.translate, + y : 'годину', + yy : translator.translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return sr_cyrl; + +}));
@@ -0,0 +1,110 @@
+//! moment.js locale configuration +//! locale : Serbian [sr] +//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jedne minute'], + mm: ['minut', 'minute', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mesec', 'meseca', 'meseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var sr = moment.defineLocale('sr', { + months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays: 'nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota'.split('_'), + weekdaysShort: 'ned._pon._uto._sre._čet._pet._sub.'.split('_'), + weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm', + LTS : 'H:mm:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm', + LLLL: 'dddd, D. MMMM YYYY H:mm' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sutra u] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedelju] [u] LT'; + case 3: + return '[u] [sredu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedelje] [u] LT', + '[prošlog] [ponedeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'pre %s', + s : 'nekoliko sekundi', + m : translator.translate, + mm : translator.translate, + h : translator.translate, + hh : translator.translate, + d : 'dan', + dd : translator.translate, + M : 'mesec', + MM : translator.translate, + y : 'godinu', + yy : translator.translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return sr; + +}));
@@ -0,0 +1,89 @@
+//! moment.js locale configuration +//! locale : Swazi [ss] +//! author : Nicolai Davies<mail@nicolai.io> : https://github.com/nicolaidavies + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + + var ss = moment.defineLocale('ss', { + months : "Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split('_'), + monthsShort : 'Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo'.split('_'), + weekdays : 'Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo'.split('_'), + weekdaysShort : 'Lis_Umb_Lsb_Les_Lsi_Lsh_Umg'.split('_'), + weekdaysMin : 'Li_Us_Lb_Lt_Ls_Lh_Ug'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[Namuhla nga] LT', + nextDay : '[Kusasa nga] LT', + nextWeek : 'dddd [nga] LT', + lastDay : '[Itolo nga] LT', + lastWeek : 'dddd [leliphelile] [nga] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'nga %s', + past : 'wenteka nga %s', + s : 'emizuzwana lomcane', + m : 'umzuzu', + mm : '%d emizuzu', + h : 'lihora', + hh : '%d emahora', + d : 'lilanga', + dd : '%d emalanga', + M : 'inyanga', + MM : '%d tinyanga', + y : 'umnyaka', + yy : '%d iminyaka' + }, + meridiemParse: /ekuseni|emini|entsambama|ebusuku/, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'ekuseni'; + } else if (hours < 15) { + return 'emini'; + } else if (hours < 19) { + return 'entsambama'; + } else { + return 'ebusuku'; + } + }, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'ekuseni') { + return hour; + } else if (meridiem === 'emini') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'entsambama' || meridiem === 'ebusuku') { + if (hour === 0) { + return 0; + } + return hour + 12; + } + }, + ordinalParse: /\d{1,2}/, + ordinal : '%d', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return ss; + +}));
@@ -0,0 +1,69 @@
+//! moment.js locale configuration +//! locale : Swedish [sv] +//! author : Jens Alm : https://github.com/ulmus + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var sv = moment.defineLocale('sv', { + months : 'januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december'.split('_'), + monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'), + weekdays : 'söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag'.split('_'), + weekdaysShort : 'sön_mån_tis_ons_tor_fre_lör'.split('_'), + weekdaysMin : 'sö_må_ti_on_to_fr_lö'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [kl.] HH:mm', + LLLL : 'dddd D MMMM YYYY [kl.] HH:mm', + lll : 'D MMM YYYY HH:mm', + llll : 'ddd D MMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Idag] LT', + nextDay: '[Imorgon] LT', + lastDay: '[Igår] LT', + nextWeek: '[På] dddd LT', + lastWeek: '[I] dddd[s] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : 'för %s sedan', + s : 'några sekunder', + m : 'en minut', + mm : '%d minuter', + h : 'en timme', + hh : '%d timmar', + d : 'en dag', + dd : '%d dagar', + M : 'en månad', + MM : '%d månader', + y : 'ett år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}(e|a)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'e' : + (b === 1) ? 'a' : + (b === 2) ? 'a' : + (b === 3) ? 'e' : 'e'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return sv; + +}));
@@ -0,0 +1,59 @@
+//! moment.js locale configuration +//! locale : Swahili [sw] +//! author : Fahad Kassim : https://github.com/fadsel + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var sw = moment.defineLocale('sw', { + months : 'Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba'.split('_'), + monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi'.split('_'), + weekdaysShort : 'Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos'.split('_'), + weekdaysMin : 'J2_J3_J4_J5_Al_Ij_J1'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[leo saa] LT', + nextDay : '[kesho saa] LT', + nextWeek : '[wiki ijayo] dddd [saat] LT', + lastDay : '[jana] LT', + lastWeek : '[wiki iliyopita] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s baadaye', + past : 'tokea %s', + s : 'hivi punde', + m : 'dakika moja', + mm : 'dakika %d', + h : 'saa limoja', + hh : 'masaa %d', + d : 'siku moja', + dd : 'masiku %d', + M : 'mwezi mmoja', + MM : 'miezi %d', + y : 'mwaka mmoja', + yy : 'miaka %d' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return sw; + +}));
@@ -0,0 +1,129 @@
+//! moment.js locale configuration +//! locale : Tamil [ta] +//! author : Arjunkumar Krishnamoorthy : https://github.com/tk120404 + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '௧', + '2': '௨', + '3': '௩', + '4': '௪', + '5': '௫', + '6': '௬', + '7': '௭', + '8': '௮', + '9': '௯', + '0': '௦' + }, numberMap = { + '௧': '1', + '௨': '2', + '௩': '3', + '௪': '4', + '௫': '5', + '௬': '6', + '௭': '7', + '௮': '8', + '௯': '9', + '௦': '0' + }; + + var ta = moment.defineLocale('ta', { + months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'), + weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'), + weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, HH:mm', + LLLL : 'dddd, D MMMM YYYY, HH:mm' + }, + calendar : { + sameDay : '[இன்று] LT', + nextDay : '[நாளை] LT', + nextWeek : 'dddd, LT', + lastDay : '[நேற்று] LT', + lastWeek : '[கடந்த வாரம்] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s இல்', + past : '%s முன்', + s : 'ஒரு சில விநாடிகள்', + m : 'ஒரு நிமிடம்', + mm : '%d நிமிடங்கள்', + h : 'ஒரு மணி நேரம்', + hh : '%d மணி நேரம்', + d : 'ஒரு நாள்', + dd : '%d நாட்கள்', + M : 'ஒரு மாதம்', + MM : '%d மாதங்கள்', + y : 'ஒரு வருடம்', + yy : '%d ஆண்டுகள்' + }, + ordinalParse: /\d{1,2}வது/, + ordinal : function (number) { + return number + 'வது'; + }, + preparse: function (string) { + return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + // refer http://ta.wikipedia.org/s/1er1 + meridiemParse: /யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/, + meridiem : function (hour, minute, isLower) { + if (hour < 2) { + return ' யாமம்'; + } else if (hour < 6) { + return ' வைகறை'; // வைகறை + } else if (hour < 10) { + return ' காலை'; // காலை + } else if (hour < 14) { + return ' நண்பகல்'; // நண்பகல் + } else if (hour < 18) { + return ' எற்பாடு'; // எற்பாடு + } else if (hour < 22) { + return ' மாலை'; // மாலை + } else { + return ' யாமம்'; + } + }, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'யாமம்') { + return hour < 2 ? hour : hour + 12; + } else if (meridiem === 'வைகறை' || meridiem === 'காலை') { + return hour; + } else if (meridiem === 'நண்பகல்') { + return hour >= 10 ? hour : hour + 12; + } else { + return hour + 12; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + return ta; + +}));
@@ -0,0 +1,89 @@
+//! moment.js locale configuration +//! locale : Telugu [te] +//! author : Krishna Chaitanya Thota : https://github.com/kcthota + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var te = moment.defineLocale('te', { + months : 'జనవరి_ఫిబ్రవరి_మార్చి_ఏప్రిల్_మే_జూన్_జూలై_ఆగస్టు_సెప్టెంబర్_అక్టోబర్_నవంబర్_డిసెంబర్'.split('_'), + monthsShort : 'జన._ఫిబ్ర._మార్చి_ఏప్రి._మే_జూన్_జూలై_ఆగ._సెప్._అక్టో._నవ._డిసె.'.split('_'), + monthsParseExact : true, + weekdays : 'ఆదివారం_సోమవారం_మంగళవారం_బుధవారం_గురువారం_శుక్రవారం_శనివారం'.split('_'), + weekdaysShort : 'ఆది_సోమ_మంగళ_బుధ_గురు_శుక్ర_శని'.split('_'), + weekdaysMin : 'ఆ_సో_మం_బు_గు_శు_శ'.split('_'), + longDateFormat : { + LT : 'A h:mm', + LTS : 'A h:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm', + LLLL : 'dddd, D MMMM YYYY, A h:mm' + }, + calendar : { + sameDay : '[నేడు] LT', + nextDay : '[రేపు] LT', + nextWeek : 'dddd, LT', + lastDay : '[నిన్న] LT', + lastWeek : '[గత] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s లో', + past : '%s క్రితం', + s : 'కొన్ని క్షణాలు', + m : 'ఒక నిమిషం', + mm : '%d నిమిషాలు', + h : 'ఒక గంట', + hh : '%d గంటలు', + d : 'ఒక రోజు', + dd : '%d రోజులు', + M : 'ఒక నెల', + MM : '%d నెలలు', + y : 'ఒక సంవత్సరం', + yy : '%d సంవత్సరాలు' + }, + ordinalParse : /\d{1,2}వ/, + ordinal : '%dవ', + meridiemParse: /రాత్రి|ఉదయం|మధ్యాహ్నం|సాయంత్రం/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'రాత్రి') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'ఉదయం') { + return hour; + } else if (meridiem === 'మధ్యాహ్నం') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'సాయంత్రం') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'రాత్రి'; + } else if (hour < 10) { + return 'ఉదయం'; + } else if (hour < 17) { + return 'మధ్యాహ్నం'; + } else if (hour < 20) { + return 'సాయంత్రం'; + } else { + return 'రాత్రి'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + return te; + +}));
@@ -0,0 +1,67 @@
+//! moment.js locale configuration +//! locale : Thai [th] +//! author : Kridsada Thanabulpong : https://github.com/sirn + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var th = moment.defineLocale('th', { + months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'), + monthsShort : 'ม.ค._ก.พ._มี.ค._เม.ย._พ.ค._มิ.ย._ก.ค._ส.ค._ก.ย._ต.ค._พ.ย._ธ.ค.'.split('_'), + monthsParseExact: true, + weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'), + weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference + weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H นาฬิกา m นาที', + LTS : 'H นาฬิกา m นาที s วินาที', + L : 'YYYY/MM/DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY เวลา H นาฬิกา m นาที', + LLLL : 'วันddddที่ D MMMM YYYY เวลา H นาฬิกา m นาที' + }, + meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/, + isPM: function (input) { + return input === 'หลังเที่ยง'; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ก่อนเที่ยง'; + } else { + return 'หลังเที่ยง'; + } + }, + calendar : { + sameDay : '[วันนี้ เวลา] LT', + nextDay : '[พรุ่งนี้ เวลา] LT', + nextWeek : 'dddd[หน้า เวลา] LT', + lastDay : '[เมื่อวานนี้ เวลา] LT', + lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'อีก %s', + past : '%sที่แล้ว', + s : 'ไม่กี่วินาที', + m : '1 นาที', + mm : '%d นาที', + h : '1 ชั่วโมง', + hh : '%d ชั่วโมง', + d : '1 วัน', + dd : '%d วัน', + M : '1 เดือน', + MM : '%d เดือน', + y : '1 ปี', + yy : '%d ปี' + } + }); + + return th; + +}));
@@ -0,0 +1,62 @@
+//! moment.js locale configuration +//! locale : Tagalog (Philippines) [tl-ph] +//! author : Dan Hagman + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var tl_ph = moment.defineLocale('tl-ph', { + months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'), + monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'), + weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'), + weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'), + weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'MM/D/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY HH:mm', + LLLL : 'dddd, MMMM DD, YYYY HH:mm' + }, + calendar : { + sameDay: '[Ngayon sa] LT', + nextDay: '[Bukas sa] LT', + nextWeek: 'dddd [sa] LT', + lastDay: '[Kahapon sa] LT', + lastWeek: 'dddd [huling linggo] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'sa loob ng %s', + past : '%s ang nakalipas', + s : 'ilang segundo', + m : 'isang minuto', + mm : '%d minuto', + h : 'isang oras', + hh : '%d oras', + d : 'isang araw', + dd : '%d araw', + M : 'isang buwan', + MM : '%d buwan', + y : 'isang taon', + yy : '%d taon' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return tl_ph; + +}));
@@ -0,0 +1,120 @@
+//! moment.js locale configuration +//! locale : Klingon [tlh] +//! author : Dominika Kruk : https://github.com/amaranthrose + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var numbersNouns = 'pagh_wa’_cha’_wej_loS_vagh_jav_Soch_chorgh_Hut'.split('_'); + + function translateFuture(output) { + var time = output; + time = (output.indexOf('jaj') !== -1) ? + time.slice(0, -3) + 'leS' : + (output.indexOf('jar') !== -1) ? + time.slice(0, -3) + 'waQ' : + (output.indexOf('DIS') !== -1) ? + time.slice(0, -3) + 'nem' : + time + ' pIq'; + return time; + } + + function translatePast(output) { + var time = output; + time = (output.indexOf('jaj') !== -1) ? + time.slice(0, -3) + 'Hu’' : + (output.indexOf('jar') !== -1) ? + time.slice(0, -3) + 'wen' : + (output.indexOf('DIS') !== -1) ? + time.slice(0, -3) + 'ben' : + time + ' ret'; + return time; + } + + function translate(number, withoutSuffix, string, isFuture) { + var numberNoun = numberAsNoun(number); + switch (string) { + case 'mm': + return numberNoun + ' tup'; + case 'hh': + return numberNoun + ' rep'; + case 'dd': + return numberNoun + ' jaj'; + case 'MM': + return numberNoun + ' jar'; + case 'yy': + return numberNoun + ' DIS'; + } + } + + function numberAsNoun(number) { + var hundred = Math.floor((number % 1000) / 100), + ten = Math.floor((number % 100) / 10), + one = number % 10, + word = ''; + if (hundred > 0) { + word += numbersNouns[hundred] + 'vatlh'; + } + if (ten > 0) { + word += ((word !== '') ? ' ' : '') + numbersNouns[ten] + 'maH'; + } + if (one > 0) { + word += ((word !== '') ? ' ' : '') + numbersNouns[one]; + } + return (word === '') ? 'pagh' : word; + } + + var tlh = moment.defineLocale('tlh', { + months : 'tera’ jar wa’_tera’ jar cha’_tera’ jar wej_tera’ jar loS_tera’ jar vagh_tera’ jar jav_tera’ jar Soch_tera’ jar chorgh_tera’ jar Hut_tera’ jar wa’maH_tera’ jar wa’maH wa’_tera’ jar wa’maH cha’'.split('_'), + monthsShort : 'jar wa’_jar cha’_jar wej_jar loS_jar vagh_jar jav_jar Soch_jar chorgh_jar Hut_jar wa’maH_jar wa’maH wa’_jar wa’maH cha’'.split('_'), + monthsParseExact : true, + weekdays : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'), + weekdaysShort : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'), + weekdaysMin : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[DaHjaj] LT', + nextDay: '[wa’leS] LT', + nextWeek: 'LLL', + lastDay: '[wa’Hu’] LT', + lastWeek: 'LLL', + sameElse: 'L' + }, + relativeTime : { + future : translateFuture, + past : translatePast, + s : 'puS lup', + m : 'wa’ tup', + mm : translate, + h : 'wa’ rep', + hh : translate, + d : 'wa’ jaj', + dd : translate, + M : 'wa’ jar', + MM : translate, + y : 'wa’ DIS', + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return tlh; + +}));
@@ -0,0 +1,90 @@
+//! moment.js locale configuration +//! locale : Turkish [tr] +//! authors : Erhan Gundogan : https://github.com/erhangundogan, +//! Burak Yiğit Kaya: https://github.com/BYK + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var suffixes = { + 1: '\'inci', + 5: '\'inci', + 8: '\'inci', + 70: '\'inci', + 80: '\'inci', + 2: '\'nci', + 7: '\'nci', + 20: '\'nci', + 50: '\'nci', + 3: '\'üncü', + 4: '\'üncü', + 100: '\'üncü', + 6: '\'ncı', + 9: '\'uncu', + 10: '\'uncu', + 30: '\'uncu', + 60: '\'ıncı', + 90: '\'ıncı' + }; + + var tr = moment.defineLocale('tr', { + months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'), + monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'), + weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'), + weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'), + weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[bugün saat] LT', + nextDay : '[yarın saat] LT', + nextWeek : '[haftaya] dddd [saat] LT', + lastDay : '[dün] LT', + lastWeek : '[geçen hafta] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s sonra', + past : '%s önce', + s : 'birkaç saniye', + m : 'bir dakika', + mm : '%d dakika', + h : 'bir saat', + hh : '%d saat', + d : 'bir gün', + dd : '%d gün', + M : 'bir ay', + MM : '%d ay', + y : 'bir yıl', + yy : '%d yıl' + }, + ordinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/, + ordinal : function (number) { + if (number === 0) { // special case for zero + return number + '\'ıncı'; + } + var a = number % 10, + b = number % 100 - a, + c = number >= 100 ? 100 : null; + return number + (suffixes[a] || suffixes[b] || suffixes[c]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return tr; + +}));
@@ -0,0 +1,91 @@
+//! moment.js locale configuration +//! locale : Talossan [tzl] +//! author : Robin van der Vliet : https://github.com/robin0van0der0v with the help of Iustì Canun + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + + // After the year there should be a slash and the amount of years since December 26, 1979 in Roman numerals. + // This is currently too difficult (maybe even impossible) to add. + var tzl = moment.defineLocale('tzl', { + months : 'Januar_Fevraglh_Març_Avrïu_Mai_Gün_Julia_Guscht_Setemvar_Listopäts_Noemvar_Zecemvar'.split('_'), + monthsShort : 'Jan_Fev_Mar_Avr_Mai_Gün_Jul_Gus_Set_Lis_Noe_Zec'.split('_'), + weekdays : 'Súladi_Lúneçi_Maitzi_Márcuri_Xhúadi_Viénerçi_Sáturi'.split('_'), + weekdaysShort : 'Súl_Lún_Mai_Már_Xhú_Vié_Sát'.split('_'), + weekdaysMin : 'Sú_Lú_Ma_Má_Xh_Vi_Sá'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM [dallas] YYYY', + LLL : 'D. MMMM [dallas] YYYY HH.mm', + LLLL : 'dddd, [li] D. MMMM [dallas] YYYY HH.mm' + }, + meridiemParse: /d\'o|d\'a/i, + isPM : function (input) { + return 'd\'o' === input.toLowerCase(); + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'd\'o' : 'D\'O'; + } else { + return isLower ? 'd\'a' : 'D\'A'; + } + }, + calendar : { + sameDay : '[oxhi à] LT', + nextDay : '[demà à] LT', + nextWeek : 'dddd [à] LT', + lastDay : '[ieiri à] LT', + lastWeek : '[sür el] dddd [lasteu à] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'osprei %s', + past : 'ja%s', + s : processRelativeTime, + m : processRelativeTime, + mm : processRelativeTime, + h : processRelativeTime, + hh : processRelativeTime, + d : processRelativeTime, + dd : processRelativeTime, + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 's': ['viensas secunds', '\'iensas secunds'], + 'm': ['\'n míut', '\'iens míut'], + 'mm': [number + ' míuts', '' + number + ' míuts'], + 'h': ['\'n þora', '\'iensa þora'], + 'hh': [number + ' þoras', '' + number + ' þoras'], + 'd': ['\'n ziua', '\'iensa ziua'], + 'dd': [number + ' ziuas', '' + number + ' ziuas'], + 'M': ['\'n mes', '\'iens mes'], + 'MM': [number + ' mesen', '' + number + ' mesen'], + 'y': ['\'n ar', '\'iens ar'], + 'yy': [number + ' ars', '' + number + ' ars'] + }; + return isFuture ? format[key][0] : (withoutSuffix ? format[key][0] : format[key][1]); + } + + return tzl; + +}));
@@ -0,0 +1,58 @@
+//! moment.js locale configuration +//! locale : Central Atlas Tamazight Latin [tzm-latn] +//! author : Abdel Said : https://github.com/abdelsaid + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var tzm_latn = moment.defineLocale('tzm-latn', { + months : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'), + monthsShort : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'), + weekdays : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), + weekdaysShort : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), + weekdaysMin : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[asdkh g] LT', + nextDay: '[aska g] LT', + nextWeek: 'dddd [g] LT', + lastDay: '[assant g] LT', + lastWeek: 'dddd [g] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dadkh s yan %s', + past : 'yan %s', + s : 'imik', + m : 'minuḍ', + mm : '%d minuḍ', + h : 'saɛa', + hh : '%d tassaɛin', + d : 'ass', + dd : '%d ossan', + M : 'ayowr', + MM : '%d iyyirn', + y : 'asgas', + yy : '%d isgasn' + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + return tzm_latn; + +}));
@@ -0,0 +1,58 @@
+//! moment.js locale configuration +//! locale : Central Atlas Tamazight [tzm] +//! author : Abdel Said : https://github.com/abdelsaid + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var tzm = moment.defineLocale('tzm', { + months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[ⴰⵙⴷⵅ ⴴ] LT', + nextDay: '[ⴰⵙⴽⴰ ⴴ] LT', + nextWeek: 'dddd [ⴴ] LT', + lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT', + lastWeek: 'dddd [ⴴ] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s', + past : 'ⵢⴰⵏ %s', + s : 'ⵉⵎⵉⴽ', + m : 'ⵎⵉⵏⵓⴺ', + mm : '%d ⵎⵉⵏⵓⴺ', + h : 'ⵙⴰⵄⴰ', + hh : '%d ⵜⴰⵙⵙⴰⵄⵉⵏ', + d : 'ⴰⵙⵙ', + dd : '%d oⵙⵙⴰⵏ', + M : 'ⴰⵢoⵓⵔ', + MM : '%d ⵉⵢⵢⵉⵔⵏ', + y : 'ⴰⵙⴳⴰⵙ', + yy : '%d ⵉⵙⴳⴰⵙⵏ' + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + return tzm; + +}));
@@ -0,0 +1,146 @@
+//! moment.js locale configuration +//! locale : Ukrainian [uk] +//! author : zemlanin : https://github.com/zemlanin +//! Author : Menelion Elensúle : https://github.com/Oire + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); + } + function relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'хвилина_хвилини_хвилин' : 'хвилину_хвилини_хвилин', + 'hh': withoutSuffix ? 'година_години_годин' : 'годину_години_годин', + 'dd': 'день_дні_днів', + 'MM': 'місяць_місяці_місяців', + 'yy': 'рік_роки_років' + }; + if (key === 'm') { + return withoutSuffix ? 'хвилина' : 'хвилину'; + } + else if (key === 'h') { + return withoutSuffix ? 'година' : 'годину'; + } + else { + return number + ' ' + plural(format[key], +number); + } + } + function weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'), + 'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'), + 'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_') + }, + nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ? + 'accusative' : + ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ? + 'genitive' : + 'nominative'); + return weekdays[nounCase][m.day()]; + } + function processHoursFunction(str) { + return function () { + return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT'; + }; + } + + var uk = moment.defineLocale('uk', { + months : { + 'format': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_'), + 'standalone': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_') + }, + monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'), + weekdays : weekdaysCaseReplace, + weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY р.', + LLL : 'D MMMM YYYY р., HH:mm', + LLLL : 'dddd, D MMMM YYYY р., HH:mm' + }, + calendar : { + sameDay: processHoursFunction('[Сьогодні '), + nextDay: processHoursFunction('[Завтра '), + lastDay: processHoursFunction('[Вчора '), + nextWeek: processHoursFunction('[У] dddd ['), + lastWeek: function () { + switch (this.day()) { + case 0: + case 3: + case 5: + case 6: + return processHoursFunction('[Минулої] dddd [').call(this); + case 1: + case 2: + case 4: + return processHoursFunction('[Минулого] dddd [').call(this); + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'за %s', + past : '%s тому', + s : 'декілька секунд', + m : relativeTimeWithPlural, + mm : relativeTimeWithPlural, + h : 'годину', + hh : relativeTimeWithPlural, + d : 'день', + dd : relativeTimeWithPlural, + M : 'місяць', + MM : relativeTimeWithPlural, + y : 'рік', + yy : relativeTimeWithPlural + }, + // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason + meridiemParse: /ночі|ранку|дня|вечора/, + isPM: function (input) { + return /^(дня|вечора)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночі'; + } else if (hour < 12) { + return 'ранку'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечора'; + } + }, + ordinalParse: /\d{1,2}-(й|го)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + case 'w': + case 'W': + return number + '-й'; + case 'D': + return number + '-го'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + return uk; + +}));
@@ -0,0 +1,58 @@
+//! moment.js locale configuration +//! locale : Uzbek [uz] +//! author : Sardor Muminov : https://github.com/muminoff + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var uz = moment.defineLocale('uz', { + months : 'январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр'.split('_'), + monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'), + weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'), + weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'), + weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'D MMMM YYYY, dddd HH:mm' + }, + calendar : { + sameDay : '[Бугун соат] LT [да]', + nextDay : '[Эртага] LT [да]', + nextWeek : 'dddd [куни соат] LT [да]', + lastDay : '[Кеча соат] LT [да]', + lastWeek : '[Утган] dddd [куни соат] LT [да]', + sameElse : 'L' + }, + relativeTime : { + future : 'Якин %s ичида', + past : 'Бир неча %s олдин', + s : 'фурсат', + m : 'бир дакика', + mm : '%d дакика', + h : 'бир соат', + hh : '%d соат', + d : 'бир кун', + dd : '%d кун', + M : 'бир ой', + MM : '%d ой', + y : 'бир йил', + yy : '%d йил' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 4th is the first week of the year. + } + }); + + return uz; + +}));
@@ -0,0 +1,79 @@
+//! moment.js locale configuration +//! locale : Vietnamese [vi] +//! author : Bang Nguyen : https://github.com/bangnk + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var vi = moment.defineLocale('vi', { + months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'), + monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'), + monthsParseExact : true, + weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'), + weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + weekdaysParseExact : true, + meridiemParse: /sa|ch/i, + isPM : function (input) { + return /^ch$/i.test(input); + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower ? 'sa' : 'SA'; + } else { + return isLower ? 'ch' : 'CH'; + } + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM [năm] YYYY', + LLL : 'D MMMM [năm] YYYY HH:mm', + LLLL : 'dddd, D MMMM [năm] YYYY HH:mm', + l : 'DD/M/YYYY', + ll : 'D MMM YYYY', + lll : 'D MMM YYYY HH:mm', + llll : 'ddd, D MMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Hôm nay lúc] LT', + nextDay: '[Ngày mai lúc] LT', + nextWeek: 'dddd [tuần tới lúc] LT', + lastDay: '[Hôm qua lúc] LT', + lastWeek: 'dddd [tuần rồi lúc] LT', + sameElse: 'L' + }, + relativeTime : { + future : '%s tới', + past : '%s trước', + s : 'vài giây', + m : 'một phút', + mm : '%d phút', + h : 'một giờ', + hh : '%d giờ', + d : 'một ngày', + dd : '%d ngày', + M : 'một tháng', + MM : '%d tháng', + y : 'một năm', + yy : '%d năm' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return vi; + +}));
@@ -0,0 +1,68 @@
+//! moment.js locale configuration +//! locale : Pseudo [x-pseudo] +//! author : Andrew Hood : https://github.com/andrewhood125 + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var x_pseudo = moment.defineLocale('x-pseudo', { + months : 'J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér'.split('_'), + monthsShort : 'J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc'.split('_'), + monthsParseExact : true, + weekdays : 'S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý'.split('_'), + weekdaysShort : 'S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát'.split('_'), + weekdaysMin : 'S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[T~ódá~ý át] LT', + nextDay : '[T~ómó~rró~w át] LT', + nextWeek : 'dddd [át] LT', + lastDay : '[Ý~ést~érdá~ý át] LT', + lastWeek : '[L~ást] dddd [át] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'í~ñ %s', + past : '%s á~gó', + s : 'á ~féw ~sécó~ñds', + m : 'á ~míñ~úté', + mm : '%d m~íñú~tés', + h : 'á~ñ hó~úr', + hh : '%d h~óúrs', + d : 'á ~dáý', + dd : '%d d~áýs', + M : 'á ~móñ~th', + MM : '%d m~óñt~hs', + y : 'á ~ýéár', + yy : '%d ý~éárs' + }, + ordinalParse: /\d{1,2}(th|st|nd|rd)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return x_pseudo; + +}));
@@ -0,0 +1,127 @@
+//! moment.js locale configuration +//! locale : Chinese (China) [zh-cn] +//! author : suupic : https://github.com/suupic +//! author : Zeno Zeng : https://github.com/zenozeng + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var zh_cn = moment.defineLocale('zh-cn', { + months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'), + monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'), + weekdaysShort : '周日_周一_周二_周三_周四_周五_周六'.split('_'), + weekdaysMin : '日_一_二_三_四_五_六'.split('_'), + longDateFormat : { + LT : 'Ah点mm分', + LTS : 'Ah点m分s秒', + L : 'YYYY-MM-DD', + LL : 'YYYY年MMMD日', + LLL : 'YYYY年MMMD日Ah点mm分', + LLLL : 'YYYY年MMMD日ddddAh点mm分', + l : 'YYYY-MM-DD', + ll : 'YYYY年MMMD日', + lll : 'YYYY年MMMD日Ah点mm分', + llll : 'YYYY年MMMD日ddddAh点mm分' + }, + meridiemParse: /凌晨|早上|上午|中午|下午|晚上/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '凌晨' || meridiem === '早上' || + meridiem === '上午') { + return hour; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } else { + // '中午' + return hour >= 11 ? hour : hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 600) { + return '凌晨'; + } else if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : function () { + return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT'; + }, + nextDay : function () { + return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT'; + }, + lastDay : function () { + return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT'; + }, + nextWeek : function () { + var startOfWeek, prefix; + startOfWeek = moment().startOf('week'); + prefix = this.diff(startOfWeek, 'days') >= 7 ? '[下]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + lastWeek : function () { + var startOfWeek, prefix; + startOfWeek = moment().startOf('week'); + prefix = this.unix() < startOfWeek.unix() ? '[上]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + sameElse : 'LL' + }, + ordinalParse: /\d{1,2}(日|月|周)/, + ordinal : function (number, period) { + switch (period) { + case 'd': + case 'D': + case 'DDD': + return number + '日'; + case 'M': + return number + '月'; + case 'w': + case 'W': + return number + '周'; + default: + return number; + } + }, + relativeTime : { + future : '%s内', + past : '%s前', + s : '几秒', + m : '1 分钟', + mm : '%d 分钟', + h : '1 小时', + hh : '%d 小时', + d : '1 天', + dd : '%d 天', + M : '1 个月', + MM : '%d 个月', + y : '1 年', + yy : '%d 年' + }, + week : { + // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效 + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return zh_cn; + +}));
@@ -0,0 +1,104 @@
+//! moment.js locale configuration +//! locale : Chinese (Taiwan) [zh-tw] +//! author : Ben : https://github.com/ben-lin +//! author : Chris Lam : https://github.com/hehachris + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var zh_tw = moment.defineLocale('zh-tw', { + months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'), + monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'), + weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'), + weekdaysMin : '日_一_二_三_四_五_六'.split('_'), + longDateFormat : { + LT : 'Ah點mm分', + LTS : 'Ah點m分s秒', + L : 'YYYY年MMMD日', + LL : 'YYYY年MMMD日', + LLL : 'YYYY年MMMD日Ah點mm分', + LLLL : 'YYYY年MMMD日ddddAh點mm分', + l : 'YYYY年MMMD日', + ll : 'YYYY年MMMD日', + lll : 'YYYY年MMMD日Ah點mm分', + llll : 'YYYY年MMMD日ddddAh點mm分' + }, + meridiemParse: /凌晨|早上|上午|中午|下午|晚上/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') { + return hour; + } else if (meridiem === '中午') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 600) { + return '凌晨'; + } else if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : '[今天]LT', + nextDay : '[明天]LT', + nextWeek : '[下]ddddLT', + lastDay : '[昨天]LT', + lastWeek : '[上]ddddLT', + sameElse : 'L' + }, + ordinalParse: /\d{1,2}(日|月|週)/, + ordinal : function (number, period) { + switch (period) { + case 'd' : + case 'D' : + case 'DDD' : + return number + '日'; + case 'M' : + return number + '月'; + case 'w' : + case 'W' : + return number + '週'; + default : + return number; + } + }, + relativeTime : { + future : '%s內', + past : '%s前', + s : '幾秒', + m : '1 分鐘', + mm : '%d 分鐘', + h : '1 小時', + hh : '%d 小時', + d : '1 天', + dd : '%d 天', + M : '1 個月', + MM : '%d 個月', + y : '1 年', + yy : '%d 年' + } + }); + + return zh_tw; + +}));
@@ -0,0 +1,8104 @@
+;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' + && typeof require === 'function' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + //! moment.js locale configuration + //! locale : Afrikaans [af] + //! author : Werner Mollentze : https://github.com/wernerm + + var af = moment.defineLocale('af', { + months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'), + weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'), + weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'), + meridiemParse: /vm|nm/i, + isPM : function (input) { + return /^nm$/i.test(input); + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower ? 'vm' : 'VM'; + } else { + return isLower ? 'nm' : 'NM'; + } + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Vandag om] LT', + nextDay : '[Môre om] LT', + nextWeek : 'dddd [om] LT', + lastDay : '[Gister om] LT', + lastWeek : '[Laas] dddd [om] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'oor %s', + past : '%s gelede', + s : '\'n paar sekondes', + m : '\'n minuut', + mm : '%d minute', + h : '\'n uur', + hh : '%d ure', + d : '\'n dag', + dd : '%d dae', + M : '\'n maand', + MM : '%d maande', + y : '\'n jaar', + yy : '%d jaar' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter + }, + week : { + dow : 1, // Maandag is die eerste dag van die week. + doy : 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar. + } + }); + + //! moment.js locale configuration + //! locale : Arabic (Morocco) [ar-ma] + //! author : ElFadili Yassine : https://github.com/ElFadiliY + //! author : Abdel Said : https://github.com/abdelsaid + + var ar_ma = moment.defineLocale('ar-ma', { + months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[اليوم على الساعة] LT', + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'في %s', + past : 'منذ %s', + s : 'ثوان', + m : 'دقيقة', + mm : '%d دقائق', + h : 'ساعة', + hh : '%d ساعات', + d : 'يوم', + dd : '%d أيام', + M : 'شهر', + MM : '%d أشهر', + y : 'سنة', + yy : '%d سنوات' + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Arabic (Saudi Arabia) [ar-sa] + //! author : Suhail Alkowaileet : https://github.com/xsoh + + var ar_sa__symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' + }, ar_sa__numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' + }; + + var ar_sa = moment.defineLocale('ar-sa', { + months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ص'; + } else { + return 'م'; + } + }, + calendar : { + sameDay: '[اليوم على الساعة] LT', + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'في %s', + past : 'منذ %s', + s : 'ثوان', + m : 'دقيقة', + mm : '%d دقائق', + h : 'ساعة', + hh : '%d ساعات', + d : 'يوم', + dd : '%d أيام', + M : 'شهر', + MM : '%d أشهر', + y : 'سنة', + yy : '%d سنوات' + }, + preparse: function (string) { + return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) { + return ar_sa__numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return ar_sa__symbolMap[match]; + }).replace(/,/g, '،'); + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Arabic (Tunisia) [ar-tn] + + var ar_tn = moment.defineLocale('ar-tn', { + months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[اليوم على الساعة] LT', + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime: { + future: 'في %s', + past: 'منذ %s', + s: 'ثوان', + m: 'دقيقة', + mm: '%d دقائق', + h: 'ساعة', + hh: '%d ساعات', + d: 'يوم', + dd: '%d أيام', + M: 'شهر', + MM: '%d أشهر', + y: 'سنة', + yy: '%d سنوات' + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Arabic [ar] + //! author : Abdel Said: https://github.com/abdelsaid + //! changes in months, weekdays: Ahmed Elkhatib + //! Native plural forms: forabi https://github.com/forabi + + var ar__symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' + }, ar__numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' + }, pluralForm = function (n) { + return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5; + }, plurals = { + s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'], + m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'], + h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'], + d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'], + M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'], + y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام'] + }, pluralize = function (u) { + return function (number, withoutSuffix, string, isFuture) { + var f = pluralForm(number), + str = plurals[u][pluralForm(number)]; + if (f === 2) { + str = str[withoutSuffix ? 0 : 1]; + } + return str.replace(/%d/i, number); + }; + }, ar__months = [ + 'كانون الثاني يناير', + 'شباط فبراير', + 'آذار مارس', + 'نيسان أبريل', + 'أيار مايو', + 'حزيران يونيو', + 'تموز يوليو', + 'آب أغسطس', + 'أيلول سبتمبر', + 'تشرين الأول أكتوبر', + 'تشرين الثاني نوفمبر', + 'كانون الأول ديسمبر' + ]; + + var ar = moment.defineLocale('ar', { + months : ar__months, + monthsShort : ar__months, + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'D/\u200FM/\u200FYYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ص'; + } else { + return 'م'; + } + }, + calendar : { + sameDay: '[اليوم عند الساعة] LT', + nextDay: '[غدًا عند الساعة] LT', + nextWeek: 'dddd [عند الساعة] LT', + lastDay: '[أمس عند الساعة] LT', + lastWeek: 'dddd [عند الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'بعد %s', + past : 'منذ %s', + s : pluralize('s'), + m : pluralize('m'), + mm : pluralize('m'), + h : pluralize('h'), + hh : pluralize('h'), + d : pluralize('d'), + dd : pluralize('d'), + M : pluralize('M'), + MM : pluralize('M'), + y : pluralize('y'), + yy : pluralize('y') + }, + preparse: function (string) { + return string.replace(/\u200f/g, '').replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) { + return ar__numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return ar__symbolMap[match]; + }).replace(/,/g, '،'); + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Azerbaijani [az] + //! author : topchiyev : https://github.com/topchiyev + + var az__suffixes = { + 1: '-inci', + 5: '-inci', + 8: '-inci', + 70: '-inci', + 80: '-inci', + 2: '-nci', + 7: '-nci', + 20: '-nci', + 50: '-nci', + 3: '-üncü', + 4: '-üncü', + 100: '-üncü', + 6: '-ncı', + 9: '-uncu', + 10: '-uncu', + 30: '-uncu', + 60: '-ıncı', + 90: '-ıncı' + }; + + var az = moment.defineLocale('az', { + months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'), + monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'), + weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'), + weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'), + weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[bugün saat] LT', + nextDay : '[sabah saat] LT', + nextWeek : '[gələn həftə] dddd [saat] LT', + lastDay : '[dünən] LT', + lastWeek : '[keçən həftə] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s sonra', + past : '%s əvvəl', + s : 'birneçə saniyyə', + m : 'bir dəqiqə', + mm : '%d dəqiqə', + h : 'bir saat', + hh : '%d saat', + d : 'bir gün', + dd : '%d gün', + M : 'bir ay', + MM : '%d ay', + y : 'bir il', + yy : '%d il' + }, + meridiemParse: /gecə|səhər|gündüz|axşam/, + isPM : function (input) { + return /^(gündüz|axşam)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'gecə'; + } else if (hour < 12) { + return 'səhər'; + } else if (hour < 17) { + return 'gündüz'; + } else { + return 'axşam'; + } + }, + ordinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/, + ordinal : function (number) { + if (number === 0) { // special case for zero + return number + '-ıncı'; + } + var a = number % 10, + b = number % 100 - a, + c = number >= 100 ? 100 : null; + return number + (az__suffixes[a] || az__suffixes[b] || az__suffixes[c]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Belarusian [be] + //! author : Dmitry Demidov : https://github.com/demidov91 + //! author: Praleska: http://praleska.pro/ + //! Author : Menelion Elensúle : https://github.com/Oire + + function be__plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); + } + function be__relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін', + 'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін', + 'dd': 'дзень_дні_дзён', + 'MM': 'месяц_месяцы_месяцаў', + 'yy': 'год_гады_гадоў' + }; + if (key === 'm') { + return withoutSuffix ? 'хвіліна' : 'хвіліну'; + } + else if (key === 'h') { + return withoutSuffix ? 'гадзіна' : 'гадзіну'; + } + else { + return number + ' ' + be__plural(format[key], +number); + } + } + + var be = moment.defineLocale('be', { + months : { + format: 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_'), + standalone: 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_') + }, + monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'), + weekdays : { + format: 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_'), + standalone: 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'), + isFormat: /\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/ + }, + weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY г.', + LLL : 'D MMMM YYYY г., HH:mm', + LLLL : 'dddd, D MMMM YYYY г., HH:mm' + }, + calendar : { + sameDay: '[Сёння ў] LT', + nextDay: '[Заўтра ў] LT', + lastDay: '[Учора ў] LT', + nextWeek: function () { + return '[У] dddd [ў] LT'; + }, + lastWeek: function () { + switch (this.day()) { + case 0: + case 3: + case 5: + case 6: + return '[У мінулую] dddd [ў] LT'; + case 1: + case 2: + case 4: + return '[У мінулы] dddd [ў] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'праз %s', + past : '%s таму', + s : 'некалькі секунд', + m : be__relativeTimeWithPlural, + mm : be__relativeTimeWithPlural, + h : be__relativeTimeWithPlural, + hh : be__relativeTimeWithPlural, + d : 'дзень', + dd : be__relativeTimeWithPlural, + M : 'месяц', + MM : be__relativeTimeWithPlural, + y : 'год', + yy : be__relativeTimeWithPlural + }, + meridiemParse: /ночы|раніцы|дня|вечара/, + isPM : function (input) { + return /^(дня|вечара)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночы'; + } else if (hour < 12) { + return 'раніцы'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечара'; + } + }, + ordinalParse: /\d{1,2}-(і|ы|га)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + case 'w': + case 'W': + return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : number + '-ы'; + case 'D': + return number + '-га'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Bulgarian [bg] + //! author : Krasen Borisov : https://github.com/kraz + + var bg = moment.defineLocale('bg', { + months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'), + weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'D.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd, D MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[Днес в] LT', + nextDay : '[Утре в] LT', + nextWeek : 'dddd [в] LT', + lastDay : '[Вчера в] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + case 6: + return '[В изминалата] dddd [в] LT'; + case 1: + case 2: + case 4: + case 5: + return '[В изминалия] dddd [в] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'след %s', + past : 'преди %s', + s : 'няколко секунди', + m : 'минута', + mm : '%d минути', + h : 'час', + hh : '%d часа', + d : 'ден', + dd : '%d дни', + M : 'месец', + MM : '%d месеца', + y : 'година', + yy : '%d години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + ordinal : function (number) { + var lastDigit = number % 10, + last2Digits = number % 100; + if (number === 0) { + return number + '-ев'; + } else if (last2Digits === 0) { + return number + '-ен'; + } else if (last2Digits > 10 && last2Digits < 20) { + return number + '-ти'; + } else if (lastDigit === 1) { + return number + '-ви'; + } else if (lastDigit === 2) { + return number + '-ри'; + } else if (lastDigit === 7 || lastDigit === 8) { + return number + '-ми'; + } else { + return number + '-ти'; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Bengali [bn] + //! author : Kaushik Gandhi : https://github.com/kaushikgandhi + + var bn__symbolMap = { + '1': '১', + '2': '২', + '3': '৩', + '4': '৪', + '5': '৫', + '6': '৬', + '7': '৭', + '8': '৮', + '9': '৯', + '0': '০' + }, + bn__numberMap = { + '১': '1', + '২': '2', + '৩': '3', + '৪': '4', + '৫': '5', + '৬': '6', + '৭': '7', + '৮': '8', + '৯': '9', + '০': '0' + }; + + var bn = moment.defineLocale('bn', { + months : 'জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'), + monthsShort : 'জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্'.split('_'), + weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রবার_শনিবার'.split('_'), + weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্র_শনি'.split('_'), + weekdaysMin : 'রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি'.split('_'), + longDateFormat : { + LT : 'A h:mm সময়', + LTS : 'A h:mm:ss সময়', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm সময়', + LLLL : 'dddd, D MMMM YYYY, A h:mm সময়' + }, + calendar : { + sameDay : '[আজ] LT', + nextDay : '[আগামীকাল] LT', + nextWeek : 'dddd, LT', + lastDay : '[গতকাল] LT', + lastWeek : '[গত] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s পরে', + past : '%s আগে', + s : 'কয়েক সেকেন্ড', + m : 'এক মিনিট', + mm : '%d মিনিট', + h : 'এক ঘন্টা', + hh : '%d ঘন্টা', + d : 'এক দিন', + dd : '%d দিন', + M : 'এক মাস', + MM : '%d মাস', + y : 'এক বছর', + yy : '%d বছর' + }, + preparse: function (string) { + return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) { + return bn__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return bn__symbolMap[match]; + }); + }, + meridiemParse: /রাত|সকাল|দুপুর|বিকাল|রাত/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if ((meridiem === 'রাত' && hour >= 4) || + (meridiem === 'দুপুর' && hour < 5) || + meridiem === 'বিকাল') { + return hour + 12; + } else { + return hour; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'রাত'; + } else if (hour < 10) { + return 'সকাল'; + } else if (hour < 17) { + return 'দুপুর'; + } else if (hour < 20) { + return 'বিকাল'; + } else { + return 'রাত'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Tibetan [bo] + //! author : Thupten N. Chakrishar : https://github.com/vajradog + + var bo__symbolMap = { + '1': '༡', + '2': '༢', + '3': '༣', + '4': '༤', + '5': '༥', + '6': '༦', + '7': '༧', + '8': '༨', + '9': '༩', + '0': '༠' + }, + bo__numberMap = { + '༡': '1', + '༢': '2', + '༣': '3', + '༤': '4', + '༥': '5', + '༦': '6', + '༧': '7', + '༨': '8', + '༩': '9', + '༠': '0' + }; + + var bo = moment.defineLocale('bo', { + months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'), + weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + longDateFormat : { + LT : 'A h:mm', + LTS : 'A h:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm', + LLLL : 'dddd, D MMMM YYYY, A h:mm' + }, + calendar : { + sameDay : '[དི་རིང] LT', + nextDay : '[སང་ཉིན] LT', + nextWeek : '[བདུན་ཕྲག་རྗེས་མ], LT', + lastDay : '[ཁ་སང] LT', + lastWeek : '[བདུན་ཕྲག་མཐའ་མ] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ལ་', + past : '%s སྔན་ལ', + s : 'ལམ་སང', + m : 'སྐར་མ་གཅིག', + mm : '%d སྐར་མ', + h : 'ཆུ་ཚོད་གཅིག', + hh : '%d ཆུ་ཚོད', + d : 'ཉིན་གཅིག', + dd : '%d ཉིན་', + M : 'ཟླ་བ་གཅིག', + MM : '%d ཟླ་བ', + y : 'ལོ་གཅིག', + yy : '%d ལོ' + }, + preparse: function (string) { + return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) { + return bo__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return bo__symbolMap[match]; + }); + }, + meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if ((meridiem === 'མཚན་མོ' && hour >= 4) || + (meridiem === 'ཉིན་གུང' && hour < 5) || + meridiem === 'དགོང་དག') { + return hour + 12; + } else { + return hour; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'མཚན་མོ'; + } else if (hour < 10) { + return 'ཞོགས་ཀས'; + } else if (hour < 17) { + return 'ཉིན་གུང'; + } else if (hour < 20) { + return 'དགོང་དག'; + } else { + return 'མཚན་མོ'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Breton [br] + //! author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou + + function relativeTimeWithMutation(number, withoutSuffix, key) { + var format = { + 'mm': 'munutenn', + 'MM': 'miz', + 'dd': 'devezh' + }; + return number + ' ' + mutation(format[key], number); + } + function specialMutationForYears(number) { + switch (lastNumber(number)) { + case 1: + case 3: + case 4: + case 5: + case 9: + return number + ' bloaz'; + default: + return number + ' vloaz'; + } + } + function lastNumber(number) { + if (number > 9) { + return lastNumber(number % 10); + } + return number; + } + function mutation(text, number) { + if (number === 2) { + return softMutation(text); + } + return text; + } + function softMutation(text) { + var mutationTable = { + 'm': 'v', + 'b': 'v', + 'd': 'z' + }; + if (mutationTable[text.charAt(0)] === undefined) { + return text; + } + return mutationTable[text.charAt(0)] + text.substring(1); + } + + var br = moment.defineLocale('br', { + months : 'Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split('_'), + monthsShort : 'Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'), + weekdays : 'Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn'.split('_'), + weekdaysShort : 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'), + weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'h[e]mm A', + LTS : 'h[e]mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D [a viz] MMMM YYYY', + LLL : 'D [a viz] MMMM YYYY h[e]mm A', + LLLL : 'dddd, D [a viz] MMMM YYYY h[e]mm A' + }, + calendar : { + sameDay : '[Hiziv da] LT', + nextDay : '[Warc\'hoazh da] LT', + nextWeek : 'dddd [da] LT', + lastDay : '[Dec\'h da] LT', + lastWeek : 'dddd [paset da] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'a-benn %s', + past : '%s \'zo', + s : 'un nebeud segondennoù', + m : 'ur vunutenn', + mm : relativeTimeWithMutation, + h : 'un eur', + hh : '%d eur', + d : 'un devezh', + dd : relativeTimeWithMutation, + M : 'ur miz', + MM : relativeTimeWithMutation, + y : 'ur bloaz', + yy : specialMutationForYears + }, + ordinalParse: /\d{1,2}(añ|vet)/, + ordinal : function (number) { + var output = (number === 1) ? 'añ' : 'vet'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Bosnian [bs] + //! author : Nedim Cholich : https://github.com/frontyard + //! based on (hr) translation by Bojan Marković + + function bs__translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } + } + + var bs = moment.defineLocale('bs', { + months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : bs__translate, + mm : bs__translate, + h : bs__translate, + hh : bs__translate, + d : 'dan', + dd : bs__translate, + M : 'mjesec', + MM : bs__translate, + y : 'godinu', + yy : bs__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Catalan [ca] + //! author : Juan G. Hurtado : https://github.com/juanghurtado + + var ca = moment.defineLocale('ca', { + months : 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'), + monthsShort : 'gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.'.split('_'), + monthsParseExact : true, + weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'), + weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'), + weekdaysMin : 'Dg_Dl_Dt_Dc_Dj_Dv_Ds'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd D MMMM YYYY H:mm' + }, + calendar : { + sameDay : function () { + return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + nextDay : function () { + return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + lastDay : function () { + return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'en %s', + past : 'fa %s', + s : 'uns segons', + m : 'un minut', + mm : '%d minuts', + h : 'una hora', + hh : '%d hores', + d : 'un dia', + dd : '%d dies', + M : 'un mes', + MM : '%d mesos', + y : 'un any', + yy : '%d anys' + }, + ordinalParse: /\d{1,2}(r|n|t|è|a)/, + ordinal : function (number, period) { + var output = (number === 1) ? 'r' : + (number === 2) ? 'n' : + (number === 3) ? 'r' : + (number === 4) ? 't' : 'è'; + if (period === 'w' || period === 'W') { + output = 'a'; + } + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Czech [cs] + //! author : petrbela : https://github.com/petrbela + + var cs__months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_'), + cs__monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_'); + function cs__plural(n) { + return (n > 1) && (n < 5) && (~~(n / 10) !== 1); + } + function cs__translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': // a few seconds / in a few seconds / a few seconds ago + return (withoutSuffix || isFuture) ? 'pár sekund' : 'pár sekundami'; + case 'm': // a minute / in a minute / a minute ago + return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou'); + case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago + if (withoutSuffix || isFuture) { + return result + (cs__plural(number) ? 'minuty' : 'minut'); + } else { + return result + 'minutami'; + } + break; + case 'h': // an hour / in an hour / an hour ago + return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou'); + case 'hh': // 9 hours / in 9 hours / 9 hours ago + if (withoutSuffix || isFuture) { + return result + (cs__plural(number) ? 'hodiny' : 'hodin'); + } else { + return result + 'hodinami'; + } + break; + case 'd': // a day / in a day / a day ago + return (withoutSuffix || isFuture) ? 'den' : 'dnem'; + case 'dd': // 9 days / in 9 days / 9 days ago + if (withoutSuffix || isFuture) { + return result + (cs__plural(number) ? 'dny' : 'dní'); + } else { + return result + 'dny'; + } + break; + case 'M': // a month / in a month / a month ago + return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem'; + case 'MM': // 9 months / in 9 months / 9 months ago + if (withoutSuffix || isFuture) { + return result + (cs__plural(number) ? 'měsíce' : 'měsíců'); + } else { + return result + 'měsíci'; + } + break; + case 'y': // a year / in a year / a year ago + return (withoutSuffix || isFuture) ? 'rok' : 'rokem'; + case 'yy': // 9 years / in 9 years / 9 years ago + if (withoutSuffix || isFuture) { + return result + (cs__plural(number) ? 'roky' : 'let'); + } else { + return result + 'lety'; + } + break; + } + } + + var cs = moment.defineLocale('cs', { + months : cs__months, + monthsShort : cs__monthsShort, + monthsParse : (function (months, monthsShort) { + var i, _monthsParse = []; + for (i = 0; i < 12; i++) { + // use custom parser to solve problem with July (červenec) + _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i'); + } + return _monthsParse; + }(cs__months, cs__monthsShort)), + shortMonthsParse : (function (monthsShort) { + var i, _shortMonthsParse = []; + for (i = 0; i < 12; i++) { + _shortMonthsParse[i] = new RegExp('^' + monthsShort[i] + '$', 'i'); + } + return _shortMonthsParse; + }(cs__monthsShort)), + longMonthsParse : (function (months) { + var i, _longMonthsParse = []; + for (i = 0; i < 12; i++) { + _longMonthsParse[i] = new RegExp('^' + months[i] + '$', 'i'); + } + return _longMonthsParse; + }(cs__months)), + weekdays : 'neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota'.split('_'), + weekdaysShort : 'ne_po_út_st_čt_pá_so'.split('_'), + weekdaysMin : 'ne_po_út_st_čt_pá_so'.split('_'), + longDateFormat : { + LT: 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd D. MMMM YYYY H:mm', + l : 'D. M. YYYY' + }, + calendar : { + sameDay: '[dnes v] LT', + nextDay: '[zítra v] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[v neděli v] LT'; + case 1: + case 2: + return '[v] dddd [v] LT'; + case 3: + return '[ve středu v] LT'; + case 4: + return '[ve čtvrtek v] LT'; + case 5: + return '[v pátek v] LT'; + case 6: + return '[v sobotu v] LT'; + } + }, + lastDay: '[včera v] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[minulou neděli v] LT'; + case 1: + case 2: + return '[minulé] dddd [v] LT'; + case 3: + return '[minulou středu v] LT'; + case 4: + case 5: + return '[minulý] dddd [v] LT'; + case 6: + return '[minulou sobotu v] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'za %s', + past : 'před %s', + s : cs__translate, + m : cs__translate, + mm : cs__translate, + h : cs__translate, + hh : cs__translate, + d : cs__translate, + dd : cs__translate, + M : cs__translate, + MM : cs__translate, + y : cs__translate, + yy : cs__translate + }, + ordinalParse : /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Chuvash [cv] + //! author : Anatoly Mironov : https://github.com/mirontoli + + var cv = moment.defineLocale('cv', { + months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'), + monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'), + weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'), + weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'), + weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]', + LLL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm', + LLLL : 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm' + }, + calendar : { + sameDay: '[Паян] LT [сехетре]', + nextDay: '[Ыран] LT [сехетре]', + lastDay: '[Ӗнер] LT [сехетре]', + nextWeek: '[Ҫитес] dddd LT [сехетре]', + lastWeek: '[Иртнӗ] dddd LT [сехетре]', + sameElse: 'L' + }, + relativeTime : { + future : function (output) { + var affix = /сехет$/i.exec(output) ? 'рен' : /ҫул$/i.exec(output) ? 'тан' : 'ран'; + return output + affix; + }, + past : '%s каялла', + s : 'пӗр-ик ҫеккунт', + m : 'пӗр минут', + mm : '%d минут', + h : 'пӗр сехет', + hh : '%d сехет', + d : 'пӗр кун', + dd : '%d кун', + M : 'пӗр уйӑх', + MM : '%d уйӑх', + y : 'пӗр ҫул', + yy : '%d ҫул' + }, + ordinalParse: /\d{1,2}-мӗш/, + ordinal : '%d-мӗш', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Welsh [cy] + //! author : Robert Allen + + var cy = moment.defineLocale('cy', { + months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'), + monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'), + weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'), + weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'), + weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'), + weekdaysParseExact : true, + // time formats are the same as en-gb + longDateFormat: { + LT: 'HH:mm', + LTS : 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd, D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[Heddiw am] LT', + nextDay: '[Yfory am] LT', + nextWeek: 'dddd [am] LT', + lastDay: '[Ddoe am] LT', + lastWeek: 'dddd [diwethaf am] LT', + sameElse: 'L' + }, + relativeTime: { + future: 'mewn %s', + past: '%s yn ôl', + s: 'ychydig eiliadau', + m: 'munud', + mm: '%d munud', + h: 'awr', + hh: '%d awr', + d: 'diwrnod', + dd: '%d diwrnod', + M: 'mis', + MM: '%d mis', + y: 'blwyddyn', + yy: '%d flynedd' + }, + ordinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/, + // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh + ordinal: function (number) { + var b = number, + output = '', + lookup = [ + '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed + 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed + ]; + if (b > 20) { + if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) { + output = 'fed'; // not 30ain, 70ain or 90ain + } else { + output = 'ain'; + } + } else if (b > 0) { + output = lookup[b]; + } + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Danish [da] + //! author : Ulrik Nielsen : https://github.com/mrbase + + var da = moment.defineLocale('da', { + months : 'januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december'.split('_'), + monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'), + weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'), + weekdaysShort : 'søn_man_tir_ons_tor_fre_lør'.split('_'), + weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY HH:mm', + LLLL : 'dddd [d.] D. MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[I dag kl.] LT', + nextDay : '[I morgen kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[I går kl.] LT', + lastWeek : '[sidste] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'om %s', + past : '%s siden', + s : 'få sekunder', + m : 'et minut', + mm : '%d minutter', + h : 'en time', + hh : '%d timer', + d : 'en dag', + dd : '%d dage', + M : 'en måned', + MM : '%d måneder', + y : 'et år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : German (Austria) [de-at] + //! author : lluchs : https://github.com/lluchs + //! author: Menelion Elensúle: https://github.com/Oire + //! author : Martin Groller : https://github.com/MadMG + //! author : Mikolaj Dadela : https://github.com/mik01aj + + function de_at__processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eine Minute', 'einer Minute'], + 'h': ['eine Stunde', 'einer Stunde'], + 'd': ['ein Tag', 'einem Tag'], + 'dd': [number + ' Tage', number + ' Tagen'], + 'M': ['ein Monat', 'einem Monat'], + 'MM': [number + ' Monate', number + ' Monaten'], + 'y': ['ein Jahr', 'einem Jahr'], + 'yy': [number + ' Jahre', number + ' Jahren'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; + } + + var de_at = moment.defineLocale('de-at', { + months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort : 'Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + monthsParseExact : true, + weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'), + weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'), + weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY HH:mm', + LLLL : 'dddd, D. MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + relativeTime : { + future : 'in %s', + past : 'vor %s', + s : 'ein paar Sekunden', + m : de_at__processRelativeTime, + mm : '%d Minuten', + h : de_at__processRelativeTime, + hh : '%d Stunden', + d : de_at__processRelativeTime, + dd : de_at__processRelativeTime, + M : de_at__processRelativeTime, + MM : de_at__processRelativeTime, + y : de_at__processRelativeTime, + yy : de_at__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : German [de] + //! author : lluchs : https://github.com/lluchs + //! author: Menelion Elensúle: https://github.com/Oire + //! author : Mikolaj Dadela : https://github.com/mik01aj + + function de__processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eine Minute', 'einer Minute'], + 'h': ['eine Stunde', 'einer Stunde'], + 'd': ['ein Tag', 'einem Tag'], + 'dd': [number + ' Tage', number + ' Tagen'], + 'M': ['ein Monat', 'einem Monat'], + 'MM': [number + ' Monate', number + ' Monaten'], + 'y': ['ein Jahr', 'einem Jahr'], + 'yy': [number + ' Jahre', number + ' Jahren'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; + } + + var de = moment.defineLocale('de', { + months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort : 'Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + monthsParseExact : true, + weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'), + weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'), + weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY HH:mm', + LLLL : 'dddd, D. MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + relativeTime : { + future : 'in %s', + past : 'vor %s', + s : 'ein paar Sekunden', + m : de__processRelativeTime, + mm : '%d Minuten', + h : de__processRelativeTime, + hh : '%d Stunden', + d : de__processRelativeTime, + dd : de__processRelativeTime, + M : de__processRelativeTime, + MM : de__processRelativeTime, + y : de__processRelativeTime, + yy : de__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Maldivian [dv] + //! author : Jawish Hameed : https://github.com/jawish + + var dv__months = [ + 'ޖެނުއަރީ', + 'ފެބްރުއަރީ', + 'މާރިޗު', + 'އޭޕްރީލު', + 'މޭ', + 'ޖޫން', + 'ޖުލައި', + 'އޯގަސްޓު', + 'ސެޕްޓެމްބަރު', + 'އޮކްޓޯބަރު', + 'ނޮވެމްބަރު', + 'ޑިސެމްބަރު' + ], dv__weekdays = [ + 'އާދިއްތަ', + 'ހޯމަ', + 'އަންގާރަ', + 'ބުދަ', + 'ބުރާސްފަތި', + 'ހުކުރު', + 'ހޮނިހިރު' + ]; + + var dv = moment.defineLocale('dv', { + months : dv__months, + monthsShort : dv__months, + weekdays : dv__weekdays, + weekdaysShort : dv__weekdays, + weekdaysMin : 'އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި'.split('_'), + longDateFormat : { + + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'D/M/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + meridiemParse: /މކ|މފ/, + isPM : function (input) { + return 'މފ' === input; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'މކ'; + } else { + return 'މފ'; + } + }, + calendar : { + sameDay : '[މިއަދު] LT', + nextDay : '[މާދަމާ] LT', + nextWeek : 'dddd LT', + lastDay : '[އިއްޔެ] LT', + lastWeek : '[ފާއިތުވި] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : 'ތެރޭގައި %s', + past : 'ކުރިން %s', + s : 'ސިކުންތުކޮޅެއް', + m : 'މިނިޓެއް', + mm : 'މިނިޓު %d', + h : 'ގަޑިއިރެއް', + hh : 'ގަޑިއިރު %d', + d : 'ދުވަހެއް', + dd : 'ދުވަސް %d', + M : 'މަހެއް', + MM : 'މަސް %d', + y : 'އަހަރެއް', + yy : 'އަހަރު %d' + }, + preparse: function (string) { + return string.replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/,/g, '،'); + }, + week : { + dow : 7, // Sunday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + function isFunction(input) { + return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]'; + } + + //! moment.js locale configuration + //! locale : Greek [el] + //! author : Aggelos Karalias : https://github.com/mehiel + + var el = moment.defineLocale('el', { + monthsNominativeEl : 'Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος'.split('_'), + monthsGenitiveEl : 'Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου'.split('_'), + months : function (momentToFormat, format) { + if (/D/.test(format.substring(0, format.indexOf('MMMM')))) { // if there is a day number before 'MMMM' + return this._monthsGenitiveEl[momentToFormat.month()]; + } else { + return this._monthsNominativeEl[momentToFormat.month()]; + } + }, + monthsShort : 'Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ'.split('_'), + weekdays : 'Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο'.split('_'), + weekdaysShort : 'Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ'.split('_'), + weekdaysMin : 'Κυ_Δε_Τρ_Τε_Πε_Πα_Σα'.split('_'), + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'μμ' : 'ΜΜ'; + } else { + return isLower ? 'πμ' : 'ΠΜ'; + } + }, + isPM : function (input) { + return ((input + '').toLowerCase()[0] === 'μ'); + }, + meridiemParse : /[ΠΜ]\.?Μ?\.?/i, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendarEl : { + sameDay : '[Σήμερα {}] LT', + nextDay : '[Αύριο {}] LT', + nextWeek : 'dddd [{}] LT', + lastDay : '[Χθες {}] LT', + lastWeek : function () { + switch (this.day()) { + case 6: + return '[το προηγούμενο] dddd [{}] LT'; + default: + return '[την προηγούμενη] dddd [{}] LT'; + } + }, + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendarEl[key], + hours = mom && mom.hours(); + if (isFunction(output)) { + output = output.apply(mom); + } + return output.replace('{}', (hours % 12 === 1 ? 'στη' : 'στις')); + }, + relativeTime : { + future : 'σε %s', + past : '%s πριν', + s : 'λίγα δευτερόλεπτα', + m : 'ένα λεπτό', + mm : '%d λεπτά', + h : 'μία ώρα', + hh : '%d ώρες', + d : 'μία μέρα', + dd : '%d μέρες', + M : 'ένας μήνας', + MM : '%d μήνες', + y : 'ένας χρόνος', + yy : '%d χρόνια' + }, + ordinalParse: /\d{1,2}η/, + ordinal: '%dη', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : English (Australia) [en-au] + + var en_au = moment.defineLocale('en-au', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : English (Canada) [en-ca] + //! author : Jonathan Abourbih : https://github.com/jonbca + + var en_ca = moment.defineLocale('en-ca', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'YYYY-MM-DD', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY h:mm A', + LLLL : 'dddd, MMMM D, YYYY h:mm A' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } + }); + + //! moment.js locale configuration + //! locale : English (United Kingdom) [en-gb] + //! author : Chris Gedrim : https://github.com/chrisgedrim + + var en_gb = moment.defineLocale('en-gb', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : English (Ireland) [en-ie] + //! author : Chris Cartlidge : https://github.com/chriscartlidge + + var en_ie = moment.defineLocale('en-ie', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : English (New Zealand) [en-nz] + + var en_nz = moment.defineLocale('en-nz', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Esperanto [eo] + //! author : Colin Dean : https://github.com/colindean + //! komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko. + //! Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni! + + var eo = moment.defineLocale('eo', { + months : 'januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro'.split('_'), + monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec'.split('_'), + weekdays : 'Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato'.split('_'), + weekdaysShort : 'Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Ĵa_Ve_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'D[-an de] MMMM, YYYY', + LLL : 'D[-an de] MMMM, YYYY HH:mm', + LLLL : 'dddd, [la] D[-an de] MMMM, YYYY HH:mm' + }, + meridiemParse: /[ap]\.t\.m/i, + isPM: function (input) { + return input.charAt(0).toLowerCase() === 'p'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'p.t.m.' : 'P.T.M.'; + } else { + return isLower ? 'a.t.m.' : 'A.T.M.'; + } + }, + calendar : { + sameDay : '[Hodiaŭ je] LT', + nextDay : '[Morgaŭ je] LT', + nextWeek : 'dddd [je] LT', + lastDay : '[Hieraŭ je] LT', + lastWeek : '[pasinta] dddd [je] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'je %s', + past : 'antaŭ %s', + s : 'sekundoj', + m : 'minuto', + mm : '%d minutoj', + h : 'horo', + hh : '%d horoj', + d : 'tago',//ne 'diurno', ĉar estas uzita por proksimumo + dd : '%d tagoj', + M : 'monato', + MM : '%d monatoj', + y : 'jaro', + yy : '%d jaroj' + }, + ordinalParse: /\d{1,2}a/, + ordinal : '%da', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Spanish (Dominican Republic) [es-do] + + var es_do__monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_'), + es_do__monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_'); + + var es_do = moment.defineLocale('es-do', { + months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return es_do__monthsShort[m.month()]; + } else { + return es_do__monthsShortDot[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'), + weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'), + weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY h:mm A', + LLLL : 'dddd, D [de] MMMM [de] YYYY h:mm A' + }, + calendar : { + sameDay : function () { + return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextDay : function () { + return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastDay : function () { + return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'en %s', + past : 'hace %s', + s : 'unos segundos', + m : 'un minuto', + mm : '%d minutos', + h : 'una hora', + hh : '%d horas', + d : 'un día', + dd : '%d días', + M : 'un mes', + MM : '%d meses', + y : 'un año', + yy : '%d años' + }, + ordinalParse : /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Spanish [es] + //! author : Julio Napurí : https://github.com/julionc + + var es__monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_'), + es__monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_'); + + var es = moment.defineLocale('es', { + months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return es__monthsShort[m.month()]; + } else { + return es__monthsShortDot[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'), + weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'), + weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY H:mm', + LLLL : 'dddd, D [de] MMMM [de] YYYY H:mm' + }, + calendar : { + sameDay : function () { + return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextDay : function () { + return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastDay : function () { + return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'en %s', + past : 'hace %s', + s : 'unos segundos', + m : 'un minuto', + mm : '%d minutos', + h : 'una hora', + hh : '%d horas', + d : 'un día', + dd : '%d días', + M : 'un mes', + MM : '%d meses', + y : 'un año', + yy : '%d años' + }, + ordinalParse : /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Estonian [et] + //! author : Henry Kehlmann : https://github.com/madhenry + //! improvements : Illimar Tambek : https://github.com/ragulka + + function et__processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'], + 'm' : ['ühe minuti', 'üks minut'], + 'mm': [number + ' minuti', number + ' minutit'], + 'h' : ['ühe tunni', 'tund aega', 'üks tund'], + 'hh': [number + ' tunni', number + ' tundi'], + 'd' : ['ühe päeva', 'üks päev'], + 'M' : ['kuu aja', 'kuu aega', 'üks kuu'], + 'MM': [number + ' kuu', number + ' kuud'], + 'y' : ['ühe aasta', 'aasta', 'üks aasta'], + 'yy': [number + ' aasta', number + ' aastat'] + }; + if (withoutSuffix) { + return format[key][2] ? format[key][2] : format[key][1]; + } + return isFuture ? format[key][0] : format[key][1]; + } + + var et = moment.defineLocale('et', { + months : 'jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember'.split('_'), + monthsShort : 'jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets'.split('_'), + weekdays : 'pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev'.split('_'), + weekdaysShort : 'P_E_T_K_N_R_L'.split('_'), + weekdaysMin : 'P_E_T_K_N_R_L'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[Täna,] LT', + nextDay : '[Homme,] LT', + nextWeek : '[Järgmine] dddd LT', + lastDay : '[Eile,] LT', + lastWeek : '[Eelmine] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s pärast', + past : '%s tagasi', + s : et__processRelativeTime, + m : et__processRelativeTime, + mm : et__processRelativeTime, + h : et__processRelativeTime, + hh : et__processRelativeTime, + d : et__processRelativeTime, + dd : '%d päeva', + M : et__processRelativeTime, + MM : et__processRelativeTime, + y : et__processRelativeTime, + yy : et__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Basque [eu] + //! author : Eneko Illarramendi : https://github.com/eillarra + + var eu = moment.defineLocale('eu', { + months : 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split('_'), + monthsShort : 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split('_'), + monthsParseExact : true, + weekdays : 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split('_'), + weekdaysShort : 'ig._al._ar._az._og._ol._lr.'.split('_'), + weekdaysMin : 'ig_al_ar_az_og_ol_lr'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'YYYY[ko] MMMM[ren] D[a]', + LLL : 'YYYY[ko] MMMM[ren] D[a] HH:mm', + LLLL : 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm', + l : 'YYYY-M-D', + ll : 'YYYY[ko] MMM D[a]', + lll : 'YYYY[ko] MMM D[a] HH:mm', + llll : 'ddd, YYYY[ko] MMM D[a] HH:mm' + }, + calendar : { + sameDay : '[gaur] LT[etan]', + nextDay : '[bihar] LT[etan]', + nextWeek : 'dddd LT[etan]', + lastDay : '[atzo] LT[etan]', + lastWeek : '[aurreko] dddd LT[etan]', + sameElse : 'L' + }, + relativeTime : { + future : '%s barru', + past : 'duela %s', + s : 'segundo batzuk', + m : 'minutu bat', + mm : '%d minutu', + h : 'ordu bat', + hh : '%d ordu', + d : 'egun bat', + dd : '%d egun', + M : 'hilabete bat', + MM : '%d hilabete', + y : 'urte bat', + yy : '%d urte' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Persian [fa] + //! author : Ebrahim Byagowi : https://github.com/ebraminio + + var fa__symbolMap = { + '1': '۱', + '2': '۲', + '3': '۳', + '4': '۴', + '5': '۵', + '6': '۶', + '7': '۷', + '8': '۸', + '9': '۹', + '0': '۰' + }, fa__numberMap = { + '۱': '1', + '۲': '2', + '۳': '3', + '۴': '4', + '۵': '5', + '۶': '6', + '۷': '7', + '۸': '8', + '۹': '9', + '۰': '0' + }; + + var fa = moment.defineLocale('fa', { + months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + meridiemParse: /قبل از ظهر|بعد از ظهر/, + isPM: function (input) { + return /بعد از ظهر/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'قبل از ظهر'; + } else { + return 'بعد از ظهر'; + } + }, + calendar : { + sameDay : '[امروز ساعت] LT', + nextDay : '[فردا ساعت] LT', + nextWeek : 'dddd [ساعت] LT', + lastDay : '[دیروز ساعت] LT', + lastWeek : 'dddd [پیش] [ساعت] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'در %s', + past : '%s پیش', + s : 'چندین ثانیه', + m : 'یک دقیقه', + mm : '%d دقیقه', + h : 'یک ساعت', + hh : '%d ساعت', + d : 'یک روز', + dd : '%d روز', + M : 'یک ماه', + MM : '%d ماه', + y : 'یک سال', + yy : '%d سال' + }, + preparse: function (string) { + return string.replace(/[۰-۹]/g, function (match) { + return fa__numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return fa__symbolMap[match]; + }).replace(/,/g, '،'); + }, + ordinalParse: /\d{1,2}م/, + ordinal : '%dم', + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Finnish [fi] + //! author : Tarmo Aidantausta : https://github.com/bleadof + + var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '), + numbersFuture = [ + 'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden', + numbersPast[7], numbersPast[8], numbersPast[9] + ]; + function fi__translate(number, withoutSuffix, key, isFuture) { + var result = ''; + switch (key) { + case 's': + return isFuture ? 'muutaman sekunnin' : 'muutama sekunti'; + case 'm': + return isFuture ? 'minuutin' : 'minuutti'; + case 'mm': + result = isFuture ? 'minuutin' : 'minuuttia'; + break; + case 'h': + return isFuture ? 'tunnin' : 'tunti'; + case 'hh': + result = isFuture ? 'tunnin' : 'tuntia'; + break; + case 'd': + return isFuture ? 'päivän' : 'päivä'; + case 'dd': + result = isFuture ? 'päivän' : 'päivää'; + break; + case 'M': + return isFuture ? 'kuukauden' : 'kuukausi'; + case 'MM': + result = isFuture ? 'kuukauden' : 'kuukautta'; + break; + case 'y': + return isFuture ? 'vuoden' : 'vuosi'; + case 'yy': + result = isFuture ? 'vuoden' : 'vuotta'; + break; + } + result = verbalNumber(number, isFuture) + ' ' + result; + return result; + } + function verbalNumber(number, isFuture) { + return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number; + } + + var fi = moment.defineLocale('fi', { + months : 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split('_'), + monthsShort : 'tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu'.split('_'), + weekdays : 'sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai'.split('_'), + weekdaysShort : 'su_ma_ti_ke_to_pe_la'.split('_'), + weekdaysMin : 'su_ma_ti_ke_to_pe_la'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD.MM.YYYY', + LL : 'Do MMMM[ta] YYYY', + LLL : 'Do MMMM[ta] YYYY, [klo] HH.mm', + LLLL : 'dddd, Do MMMM[ta] YYYY, [klo] HH.mm', + l : 'D.M.YYYY', + ll : 'Do MMM YYYY', + lll : 'Do MMM YYYY, [klo] HH.mm', + llll : 'ddd, Do MMM YYYY, [klo] HH.mm' + }, + calendar : { + sameDay : '[tänään] [klo] LT', + nextDay : '[huomenna] [klo] LT', + nextWeek : 'dddd [klo] LT', + lastDay : '[eilen] [klo] LT', + lastWeek : '[viime] dddd[na] [klo] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s päästä', + past : '%s sitten', + s : fi__translate, + m : fi__translate, + mm : fi__translate, + h : fi__translate, + hh : fi__translate, + d : fi__translate, + dd : fi__translate, + M : fi__translate, + MM : fi__translate, + y : fi__translate, + yy : fi__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Faroese [fo] + //! author : Ragnar Johannesen : https://github.com/ragnar123 + + var fo = moment.defineLocale('fo', { + months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), + weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'), + weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'), + weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D. MMMM, YYYY HH:mm' + }, + calendar : { + sameDay : '[Í dag kl.] LT', + nextDay : '[Í morgin kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[Í gjár kl.] LT', + lastWeek : '[síðstu] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'um %s', + past : '%s síðani', + s : 'fá sekund', + m : 'ein minutt', + mm : '%d minuttir', + h : 'ein tími', + hh : '%d tímar', + d : 'ein dagur', + dd : '%d dagar', + M : 'ein mánaði', + MM : '%d mánaðir', + y : 'eitt ár', + yy : '%d ár' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : French (Canada) [fr-ca] + //! author : Jonathan Abourbih : https://github.com/jonbca + + var fr_ca = moment.defineLocale('fr-ca', { + months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), + monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), + monthsParseExact : true, + weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), + weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Aujourd\'hui à] LT', + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dans %s', + past : 'il y a %s', + s : 'quelques secondes', + m : 'une minute', + mm : '%d minutes', + h : 'une heure', + hh : '%d heures', + d : 'un jour', + dd : '%d jours', + M : 'un mois', + MM : '%d mois', + y : 'un an', + yy : '%d ans' + }, + ordinalParse: /\d{1,2}(er|e)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : 'e'); + } + }); + + //! moment.js locale configuration + //! locale : French (Switzerland) [fr-ch] + //! author : Gaspard Bucher : https://github.com/gaspard + + var fr_ch = moment.defineLocale('fr-ch', { + months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), + monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), + monthsParseExact : true, + weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), + weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Aujourd\'hui à] LT', + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dans %s', + past : 'il y a %s', + s : 'quelques secondes', + m : 'une minute', + mm : '%d minutes', + h : 'une heure', + hh : '%d heures', + d : 'un jour', + dd : '%d jours', + M : 'un mois', + MM : '%d mois', + y : 'un an', + yy : '%d ans' + }, + ordinalParse: /\d{1,2}(er|e)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : 'e'); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : French [fr] + //! author : John Fischer : https://github.com/jfroffice + + var fr = moment.defineLocale('fr', { + months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), + monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), + monthsParseExact : true, + weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), + weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Aujourd\'hui à] LT', + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dans %s', + past : 'il y a %s', + s : 'quelques secondes', + m : 'une minute', + mm : '%d minutes', + h : 'une heure', + hh : '%d heures', + d : 'un jour', + dd : '%d jours', + M : 'un mois', + MM : '%d mois', + y : 'un an', + yy : '%d ans' + }, + ordinalParse: /\d{1,2}(er|)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : ''); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Frisian [fy] + //! author : Robin van der Vliet : https://github.com/robin0van0der0v + + var fy__monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_'), + fy__monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'); + + var fy = moment.defineLocale('fy', { + months : 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return fy__monthsShortWithoutDots[m.month()]; + } else { + return fy__monthsShortWithDots[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split('_'), + weekdaysShort : 'si._mo._ti._wo._to._fr._so.'.split('_'), + weekdaysMin : 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[hjoed om] LT', + nextDay: '[moarn om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[juster om] LT', + lastWeek: '[ôfrûne] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'oer %s', + past : '%s lyn', + s : 'in pear sekonden', + m : 'ien minút', + mm : '%d minuten', + h : 'ien oere', + hh : '%d oeren', + d : 'ien dei', + dd : '%d dagen', + M : 'ien moanne', + MM : '%d moannen', + y : 'ien jier', + yy : '%d jierren' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Scottish Gaelic [gd] + //! author : Jon Ashdown : https://github.com/jonashdown + + var gd__months = [ + 'Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean', 'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal', 'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd' + ]; + + var gd__monthsShort = ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh']; + + var gd__weekdays = ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne']; + + var weekdaysShort = ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis']; + + var weekdaysMin = ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa']; + + var gd = moment.defineLocale('gd', { + months : gd__months, + monthsShort : gd__monthsShort, + monthsParseExact : true, + weekdays : gd__weekdays, + weekdaysShort : weekdaysShort, + weekdaysMin : weekdaysMin, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[An-diugh aig] LT', + nextDay : '[A-màireach aig] LT', + nextWeek : 'dddd [aig] LT', + lastDay : '[An-dè aig] LT', + lastWeek : 'dddd [seo chaidh] [aig] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'ann an %s', + past : 'bho chionn %s', + s : 'beagan diogan', + m : 'mionaid', + mm : '%d mionaidean', + h : 'uair', + hh : '%d uairean', + d : 'latha', + dd : '%d latha', + M : 'mìos', + MM : '%d mìosan', + y : 'bliadhna', + yy : '%d bliadhna' + }, + ordinalParse : /\d{1,2}(d|na|mh)/, + ordinal : function (number) { + var output = number === 1 ? 'd' : number % 10 === 2 ? 'na' : 'mh'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Galician [gl] + //! author : Juan G. Hurtado : https://github.com/juanghurtado + + var gl = moment.defineLocale('gl', { + months : 'Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro'.split('_'), + monthsShort : 'Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.'.split('_'), + monthsParseExact: true, + weekdays : 'Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado'.split('_'), + weekdaysShort : 'Dom._Lun._Mar._Mér._Xov._Ven._Sáb.'.split('_'), + weekdaysMin : 'Do_Lu_Ma_Mé_Xo_Ve_Sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd D MMMM YYYY H:mm' + }, + calendar : { + sameDay : function () { + return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; + }, + nextDay : function () { + return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; + }, + nextWeek : function () { + return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + lastDay : function () { + return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT'; + }, + lastWeek : function () { + return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : function (str) { + if (str === 'uns segundos') { + return 'nuns segundos'; + } + return 'en ' + str; + }, + past : 'hai %s', + s : 'uns segundos', + m : 'un minuto', + mm : '%d minutos', + h : 'unha hora', + hh : '%d horas', + d : 'un día', + dd : '%d días', + M : 'un mes', + MM : '%d meses', + y : 'un ano', + yy : '%d anos' + }, + ordinalParse : /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Hebrew [he] + //! author : Tomer Cohen : https://github.com/tomer + //! author : Moshe Simantov : https://github.com/DevelopmentIL + //! author : Tal Ater : https://github.com/TalAter + + var he = moment.defineLocale('he', { + months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'), + monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'), + weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'), + weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'), + weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [ב]MMMM YYYY', + LLL : 'D [ב]MMMM YYYY HH:mm', + LLLL : 'dddd, D [ב]MMMM YYYY HH:mm', + l : 'D/M/YYYY', + ll : 'D MMM YYYY', + lll : 'D MMM YYYY HH:mm', + llll : 'ddd, D MMM YYYY HH:mm' + }, + calendar : { + sameDay : '[היום ב־]LT', + nextDay : '[מחר ב־]LT', + nextWeek : 'dddd [בשעה] LT', + lastDay : '[אתמול ב־]LT', + lastWeek : '[ביום] dddd [האחרון בשעה] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'בעוד %s', + past : 'לפני %s', + s : 'מספר שניות', + m : 'דקה', + mm : '%d דקות', + h : 'שעה', + hh : function (number) { + if (number === 2) { + return 'שעתיים'; + } + return number + ' שעות'; + }, + d : 'יום', + dd : function (number) { + if (number === 2) { + return 'יומיים'; + } + return number + ' ימים'; + }, + M : 'חודש', + MM : function (number) { + if (number === 2) { + return 'חודשיים'; + } + return number + ' חודשים'; + }, + y : 'שנה', + yy : function (number) { + if (number === 2) { + return 'שנתיים'; + } else if (number % 10 === 0 && number !== 10) { + return number + ' שנה'; + } + return number + ' שנים'; + } + }, + meridiemParse: /אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i, + isPM : function (input) { + return /^(אחה"צ|אחרי הצהריים|בערב)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 5) { + return 'לפנות בוקר'; + } else if (hour < 10) { + return 'בבוקר'; + } else if (hour < 12) { + return isLower ? 'לפנה"צ' : 'לפני הצהריים'; + } else if (hour < 18) { + return isLower ? 'אחה"צ' : 'אחרי הצהריים'; + } else { + return 'בערב'; + } + } + }); + + //! moment.js locale configuration + //! locale : Hindi [hi] + //! author : Mayank Singhal : https://github.com/mayanksinghal + + var hi__symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + hi__numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var hi = moment.defineLocale('hi', { + months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'), + monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'), + monthsParseExact: true, + weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm बजे', + LTS : 'A h:mm:ss बजे', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm बजे', + LLLL : 'dddd, D MMMM YYYY, A h:mm बजे' + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[कल] LT', + nextWeek : 'dddd, LT', + lastDay : '[कल] LT', + lastWeek : '[पिछले] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s में', + past : '%s पहले', + s : 'कुछ ही क्षण', + m : 'एक मिनट', + mm : '%d मिनट', + h : 'एक घंटा', + hh : '%d घंटे', + d : 'एक दिन', + dd : '%d दिन', + M : 'एक महीने', + MM : '%d महीने', + y : 'एक वर्ष', + yy : '%d वर्ष' + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return hi__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return hi__symbolMap[match]; + }); + }, + // Hindi notation for meridiems are quite fuzzy in practice. While there exists + // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi. + meridiemParse: /रात|सुबह|दोपहर|शाम/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सुबह') { + return hour; + } else if (meridiem === 'दोपहर') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'शाम') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'रात'; + } else if (hour < 10) { + return 'सुबह'; + } else if (hour < 17) { + return 'दोपहर'; + } else if (hour < 20) { + return 'शाम'; + } else { + return 'रात'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Croatian [hr] + //! author : Bojan Marković : https://github.com/bmarkovic + + function hr__translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } + } + + var hr = moment.defineLocale('hr', { + months : { + format: 'siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca'.split('_'), + standalone: 'siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_') + }, + monthsShort : 'sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'), + monthsParseExact: true, + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : hr__translate, + mm : hr__translate, + h : hr__translate, + hh : hr__translate, + d : 'dan', + dd : hr__translate, + M : 'mjesec', + MM : hr__translate, + y : 'godinu', + yy : hr__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Hungarian [hu] + //! author : Adam Brunner : https://github.com/adambrunner + + var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' '); + function hu__translate(number, withoutSuffix, key, isFuture) { + var num = number, + suffix; + switch (key) { + case 's': + return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce'; + case 'm': + return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce'); + case 'mm': + return num + (isFuture || withoutSuffix ? ' perc' : ' perce'); + case 'h': + return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája'); + case 'hh': + return num + (isFuture || withoutSuffix ? ' óra' : ' órája'); + case 'd': + return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja'); + case 'dd': + return num + (isFuture || withoutSuffix ? ' nap' : ' napja'); + case 'M': + return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); + case 'MM': + return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); + case 'y': + return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve'); + case 'yy': + return num + (isFuture || withoutSuffix ? ' év' : ' éve'); + } + return ''; + } + function week(isFuture) { + return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]'; + } + + var hu = moment.defineLocale('hu', { + months : 'január_február_március_április_május_június_július_augusztus_szeptember_október_november_december'.split('_'), + monthsShort : 'jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec'.split('_'), + weekdays : 'vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat'.split('_'), + weekdaysShort : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'), + weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'YYYY.MM.DD.', + LL : 'YYYY. MMMM D.', + LLL : 'YYYY. MMMM D. H:mm', + LLLL : 'YYYY. MMMM D., dddd H:mm' + }, + meridiemParse: /de|du/i, + isPM: function (input) { + return input.charAt(1).toLowerCase() === 'u'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower === true ? 'de' : 'DE'; + } else { + return isLower === true ? 'du' : 'DU'; + } + }, + calendar : { + sameDay : '[ma] LT[-kor]', + nextDay : '[holnap] LT[-kor]', + nextWeek : function () { + return week.call(this, true); + }, + lastDay : '[tegnap] LT[-kor]', + lastWeek : function () { + return week.call(this, false); + }, + sameElse : 'L' + }, + relativeTime : { + future : '%s múlva', + past : '%s', + s : hu__translate, + m : hu__translate, + mm : hu__translate, + h : hu__translate, + hh : hu__translate, + d : hu__translate, + dd : hu__translate, + M : hu__translate, + MM : hu__translate, + y : hu__translate, + yy : hu__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Armenian [hy-am] + //! author : Armendarabyan : https://github.com/armendarabyan + + var hy_am = moment.defineLocale('hy-am', { + months : { + format: 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_'), + standalone: 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_') + }, + monthsShort : 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'), + weekdays : 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_'), + weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY թ.', + LLL : 'D MMMM YYYY թ., HH:mm', + LLLL : 'dddd, D MMMM YYYY թ., HH:mm' + }, + calendar : { + sameDay: '[այսօր] LT', + nextDay: '[վաղը] LT', + lastDay: '[երեկ] LT', + nextWeek: function () { + return 'dddd [օրը ժամը] LT'; + }, + lastWeek: function () { + return '[անցած] dddd [օրը ժամը] LT'; + }, + sameElse: 'L' + }, + relativeTime : { + future : '%s հետո', + past : '%s առաջ', + s : 'մի քանի վայրկյան', + m : 'րոպե', + mm : '%d րոպե', + h : 'ժամ', + hh : '%d ժամ', + d : 'օր', + dd : '%d օր', + M : 'ամիս', + MM : '%d ամիս', + y : 'տարի', + yy : '%d տարի' + }, + meridiemParse: /գիշերվա|առավոտվա|ցերեկվա|երեկոյան/, + isPM: function (input) { + return /^(ցերեկվա|երեկոյան)$/.test(input); + }, + meridiem : function (hour) { + if (hour < 4) { + return 'գիշերվա'; + } else if (hour < 12) { + return 'առավոտվա'; + } else if (hour < 17) { + return 'ցերեկվա'; + } else { + return 'երեկոյան'; + } + }, + ordinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/, + ordinal: function (number, period) { + switch (period) { + case 'DDD': + case 'w': + case 'W': + case 'DDDo': + if (number === 1) { + return number + '-ին'; + } + return number + '-րդ'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Indonesian [id] + //! author : Mohammad Satrio Utomo : https://github.com/tyok + //! reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan + + var id = moment.defineLocale('id', { + months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu'.split('_'), + weekdaysShort : 'Min_Sen_Sel_Rab_Kam_Jum_Sab'.split('_'), + weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sb'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /pagi|siang|sore|malam/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'siang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sore' || meridiem === 'malam') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'siang'; + } else if (hours < 19) { + return 'sore'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Besok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kemarin pukul] LT', + lastWeek : 'dddd [lalu pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'dalam %s', + past : '%s yang lalu', + s : 'beberapa detik', + m : 'semenit', + mm : '%d menit', + h : 'sejam', + hh : '%d jam', + d : 'sehari', + dd : '%d hari', + M : 'sebulan', + MM : '%d bulan', + y : 'setahun', + yy : '%d tahun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Icelandic [is] + //! author : Hinrik Örn Sigurðsson : https://github.com/hinrik + + function is__plural(n) { + if (n % 100 === 11) { + return true; + } else if (n % 10 === 1) { + return false; + } + return true; + } + function is__translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum'; + case 'm': + return withoutSuffix ? 'mínúta' : 'mínútu'; + case 'mm': + if (is__plural(number)) { + return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum'); + } else if (withoutSuffix) { + return result + 'mínúta'; + } + return result + 'mínútu'; + case 'hh': + if (is__plural(number)) { + return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum'); + } + return result + 'klukkustund'; + case 'd': + if (withoutSuffix) { + return 'dagur'; + } + return isFuture ? 'dag' : 'degi'; + case 'dd': + if (is__plural(number)) { + if (withoutSuffix) { + return result + 'dagar'; + } + return result + (isFuture ? 'daga' : 'dögum'); + } else if (withoutSuffix) { + return result + 'dagur'; + } + return result + (isFuture ? 'dag' : 'degi'); + case 'M': + if (withoutSuffix) { + return 'mánuður'; + } + return isFuture ? 'mánuð' : 'mánuði'; + case 'MM': + if (is__plural(number)) { + if (withoutSuffix) { + return result + 'mánuðir'; + } + return result + (isFuture ? 'mánuði' : 'mánuðum'); + } else if (withoutSuffix) { + return result + 'mánuður'; + } + return result + (isFuture ? 'mánuð' : 'mánuði'); + case 'y': + return withoutSuffix || isFuture ? 'ár' : 'ári'; + case 'yy': + if (is__plural(number)) { + return result + (withoutSuffix || isFuture ? 'ár' : 'árum'); + } + return result + (withoutSuffix || isFuture ? 'ár' : 'ári'); + } + } + + var is = moment.defineLocale('is', { + months : 'janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des'.split('_'), + weekdays : 'sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur'.split('_'), + weekdaysShort : 'sun_mán_þri_mið_fim_fös_lau'.split('_'), + weekdaysMin : 'Su_Má_Þr_Mi_Fi_Fö_La'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] H:mm', + LLLL : 'dddd, D. MMMM YYYY [kl.] H:mm' + }, + calendar : { + sameDay : '[í dag kl.] LT', + nextDay : '[á morgun kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[í gær kl.] LT', + lastWeek : '[síðasta] dddd [kl.] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'eftir %s', + past : 'fyrir %s síðan', + s : is__translate, + m : is__translate, + mm : is__translate, + h : 'klukkustund', + hh : is__translate, + d : is__translate, + dd : is__translate, + M : is__translate, + MM : is__translate, + y : is__translate, + yy : is__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Italian [it] + //! author : Lorenzo : https://github.com/aliem + //! author: Mattia Larentis: https://github.com/nostalgiaz + + var it = moment.defineLocale('it', { + months : 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split('_'), + monthsShort : 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'), + weekdays : 'Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato'.split('_'), + weekdaysShort : 'Dom_Lun_Mar_Mer_Gio_Ven_Sab'.split('_'), + weekdaysMin : 'Do_Lu_Ma_Me_Gi_Ve_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Oggi alle] LT', + nextDay: '[Domani alle] LT', + nextWeek: 'dddd [alle] LT', + lastDay: '[Ieri alle] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[la scorsa] dddd [alle] LT'; + default: + return '[lo scorso] dddd [alle] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : function (s) { + return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s; + }, + past : '%s fa', + s : 'alcuni secondi', + m : 'un minuto', + mm : '%d minuti', + h : 'un\'ora', + hh : '%d ore', + d : 'un giorno', + dd : '%d giorni', + M : 'un mese', + MM : '%d mesi', + y : 'un anno', + yy : '%d anni' + }, + ordinalParse : /\d{1,2}º/, + ordinal: '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Japanese [ja] + //! author : LI Long : https://github.com/baryon + + var ja = moment.defineLocale('ja', { + months : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + weekdays : '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'), + weekdaysShort : '日_月_火_水_木_金_土'.split('_'), + weekdaysMin : '日_月_火_水_木_金_土'.split('_'), + longDateFormat : { + LT : 'Ah時m分', + LTS : 'Ah時m分s秒', + L : 'YYYY/MM/DD', + LL : 'YYYY年M月D日', + LLL : 'YYYY年M月D日Ah時m分', + LLLL : 'YYYY年M月D日Ah時m分 dddd' + }, + meridiemParse: /午前|午後/i, + isPM : function (input) { + return input === '午後'; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return '午前'; + } else { + return '午後'; + } + }, + calendar : { + sameDay : '[今日] LT', + nextDay : '[明日] LT', + nextWeek : '[来週]dddd LT', + lastDay : '[昨日] LT', + lastWeek : '[前週]dddd LT', + sameElse : 'L' + }, + ordinalParse : /\d{1,2}日/, + ordinal : function (number, period) { + switch (period) { + case 'd': + case 'D': + case 'DDD': + return number + '日'; + default: + return number; + } + }, + relativeTime : { + future : '%s後', + past : '%s前', + s : '数秒', + m : '1分', + mm : '%d分', + h : '1時間', + hh : '%d時間', + d : '1日', + dd : '%d日', + M : '1ヶ月', + MM : '%dヶ月', + y : '1年', + yy : '%d年' + } + }); + + //! moment.js locale configuration + //! locale : Japanese [jv] + //! author : Rony Lantip : https://github.com/lantip + //! reference: http://jv.wikipedia.org/wiki/Basa_Jawa + + var jv = moment.defineLocale('jv', { + months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des'.split('_'), + weekdays : 'Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu'.split('_'), + weekdaysShort : 'Min_Sen_Sel_Reb_Kem_Jem_Sep'.split('_'), + weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sp'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /enjing|siyang|sonten|ndalu/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'enjing') { + return hour; + } else if (meridiem === 'siyang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sonten' || meridiem === 'ndalu') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'enjing'; + } else if (hours < 15) { + return 'siyang'; + } else if (hours < 19) { + return 'sonten'; + } else { + return 'ndalu'; + } + }, + calendar : { + sameDay : '[Dinten puniko pukul] LT', + nextDay : '[Mbenjang pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kala wingi pukul] LT', + lastWeek : 'dddd [kepengker pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'wonten ing %s', + past : '%s ingkang kepengker', + s : 'sawetawis detik', + m : 'setunggal menit', + mm : '%d menit', + h : 'setunggal jam', + hh : '%d jam', + d : 'sedinten', + dd : '%d dinten', + M : 'sewulan', + MM : '%d wulan', + y : 'setaun', + yy : '%d taun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Georgian [ka] + //! author : Irakli Janiashvili : https://github.com/irakli-janiashvili + + var ka = moment.defineLocale('ka', { + months : { + standalone: 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'), + format: 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_') + }, + monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'), + weekdays : { + standalone: 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'), + format: 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_'), + isFormat: /(წინა|შემდეგ)/ + }, + weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'), + weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[დღეს] LT[-ზე]', + nextDay : '[ხვალ] LT[-ზე]', + lastDay : '[გუშინ] LT[-ზე]', + nextWeek : '[შემდეგ] dddd LT[-ზე]', + lastWeek : '[წინა] dddd LT-ზე', + sameElse : 'L' + }, + relativeTime : { + future : function (s) { + return (/(წამი|წუთი|საათი|წელი)/).test(s) ? + s.replace(/ი$/, 'ში') : + s + 'ში'; + }, + past : function (s) { + if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) { + return s.replace(/(ი|ე)$/, 'ის წინ'); + } + if ((/წელი/).test(s)) { + return s.replace(/წელი$/, 'წლის წინ'); + } + }, + s : 'რამდენიმე წამი', + m : 'წუთი', + mm : '%d წუთი', + h : 'საათი', + hh : '%d საათი', + d : 'დღე', + dd : '%d დღე', + M : 'თვე', + MM : '%d თვე', + y : 'წელი', + yy : '%d წელი' + }, + ordinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/, + ordinal : function (number) { + if (number === 0) { + return number; + } + if (number === 1) { + return number + '-ლი'; + } + if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) { + return 'მე-' + number; + } + return number + '-ე'; + }, + week : { + dow : 1, + doy : 7 + } + }); + + //! moment.js locale configuration + //! locale : Kazakh [kk] + //! authors : Nurlan Rakhimzhanov : https://github.com/nurlan + + var kk__suffixes = { + 0: '-ші', + 1: '-ші', + 2: '-ші', + 3: '-ші', + 4: '-ші', + 5: '-ші', + 6: '-шы', + 7: '-ші', + 8: '-ші', + 9: '-шы', + 10: '-шы', + 20: '-шы', + 30: '-шы', + 40: '-шы', + 50: '-ші', + 60: '-шы', + 70: '-ші', + 80: '-ші', + 90: '-шы', + 100: '-ші' + }; + + var kk = moment.defineLocale('kk', { + months : 'қаңтар_ақпан_наурыз_сәуір_мамыр_маусым_шілде_тамыз_қыркүйек_қазан_қараша_желтоқсан'.split('_'), + monthsShort : 'қаң_ақп_нау_сәу_мам_мау_шіл_там_қыр_қаз_қар_жел'.split('_'), + weekdays : 'жексенбі_дүйсенбі_сейсенбі_сәрсенбі_бейсенбі_жұма_сенбі'.split('_'), + weekdaysShort : 'жек_дүй_сей_сәр_бей_жұм_сен'.split('_'), + weekdaysMin : 'жк_дй_сй_ср_бй_жм_сн'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Бүгін сағат] LT', + nextDay : '[Ертең сағат] LT', + nextWeek : 'dddd [сағат] LT', + lastDay : '[Кеше сағат] LT', + lastWeek : '[Өткен аптаның] dddd [сағат] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ішінде', + past : '%s бұрын', + s : 'бірнеше секунд', + m : 'бір минут', + mm : '%d минут', + h : 'бір сағат', + hh : '%d сағат', + d : 'бір күн', + dd : '%d күн', + M : 'бір ай', + MM : '%d ай', + y : 'бір жыл', + yy : '%d жыл' + }, + ordinalParse: /\d{1,2}-(ші|шы)/, + ordinal : function (number) { + var a = number % 10, + b = number >= 100 ? 100 : null; + return number + (kk__suffixes[number] || kk__suffixes[a] || kk__suffixes[b]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Cambodian [km] + //! author : Kruy Vanna : https://github.com/kruyvanna + + var km = moment.defineLocale('km', { + months: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + monthsShort: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + longDateFormat: { + LT: 'HH:mm', + LTS : 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd, D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[ថ្ងៃនេះ ម៉ោង] LT', + nextDay: '[ស្អែក ម៉ោង] LT', + nextWeek: 'dddd [ម៉ោង] LT', + lastDay: '[ម្សិលមិញ ម៉ោង] LT', + lastWeek: 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT', + sameElse: 'L' + }, + relativeTime: { + future: '%sទៀត', + past: '%sមុន', + s: 'ប៉ុន្មានវិនាទី', + m: 'មួយនាទី', + mm: '%d នាទី', + h: 'មួយម៉ោង', + hh: '%d ម៉ោង', + d: 'មួយថ្ងៃ', + dd: '%d ថ្ងៃ', + M: 'មួយខែ', + MM: '%d ខែ', + y: 'មួយឆ្នាំ', + yy: '%d ឆ្នាំ' + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Korean [ko] + //! + //! authors + //! + //! - Kyungwook, Park : https://github.com/kyungw00k + //! - Jeeeyul Lee <jeeeyul@gmail.com> + + var ko = moment.defineLocale('ko', { + months : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'), + monthsShort : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'), + weekdays : '일요일_월요일_화요일_수요일_목요일_금요일_토요일'.split('_'), + weekdaysShort : '일_월_화_수_목_금_토'.split('_'), + weekdaysMin : '일_월_화_수_목_금_토'.split('_'), + longDateFormat : { + LT : 'A h시 m분', + LTS : 'A h시 m분 s초', + L : 'YYYY.MM.DD', + LL : 'YYYY년 MMMM D일', + LLL : 'YYYY년 MMMM D일 A h시 m분', + LLLL : 'YYYY년 MMMM D일 dddd A h시 m분' + }, + calendar : { + sameDay : '오늘 LT', + nextDay : '내일 LT', + nextWeek : 'dddd LT', + lastDay : '어제 LT', + lastWeek : '지난주 dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s 후', + past : '%s 전', + s : '몇 초', + ss : '%d초', + m : '일분', + mm : '%d분', + h : '한 시간', + hh : '%d시간', + d : '하루', + dd : '%d일', + M : '한 달', + MM : '%d달', + y : '일 년', + yy : '%d년' + }, + ordinalParse : /\d{1,2}일/, + ordinal : '%d일', + meridiemParse : /오전|오후/, + isPM : function (token) { + return token === '오후'; + }, + meridiem : function (hour, minute, isUpper) { + return hour < 12 ? '오전' : '오후'; + } + }); + + //! moment.js locale configuration + //! locale : Kyrgyz [ky] + //! author : Chyngyz Arystan uulu : https://github.com/chyngyz + + + var ky__suffixes = { + 0: '-чү', + 1: '-чи', + 2: '-чи', + 3: '-чү', + 4: '-чү', + 5: '-чи', + 6: '-чы', + 7: '-чи', + 8: '-чи', + 9: '-чу', + 10: '-чу', + 20: '-чы', + 30: '-чу', + 40: '-чы', + 50: '-чү', + 60: '-чы', + 70: '-чи', + 80: '-чи', + 90: '-чу', + 100: '-чү' + }; + + var ky = moment.defineLocale('ky', { + months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + monthsShort : 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'), + weekdays : 'Жекшемби_Дүйшөмбү_Шейшемби_Шаршемби_Бейшемби_Жума_Ишемби'.split('_'), + weekdaysShort : 'Жек_Дүй_Шей_Шар_Бей_Жум_Ише'.split('_'), + weekdaysMin : 'Жк_Дй_Шй_Шр_Бй_Жм_Иш'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Бүгүн саат] LT', + nextDay : '[Эртең саат] LT', + nextWeek : 'dddd [саат] LT', + lastDay : '[Кече саат] LT', + lastWeek : '[Өткен аптанын] dddd [күнү] [саат] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ичинде', + past : '%s мурун', + s : 'бирнече секунд', + m : 'бир мүнөт', + mm : '%d мүнөт', + h : 'бир саат', + hh : '%d саат', + d : 'бир күн', + dd : '%d күн', + M : 'бир ай', + MM : '%d ай', + y : 'бир жыл', + yy : '%d жыл' + }, + ordinalParse: /\d{1,2}-(чи|чы|чү|чу)/, + ordinal : function (number) { + var a = number % 10, + b = number >= 100 ? 100 : null; + return number + (ky__suffixes[number] || ky__suffixes[a] || ky__suffixes[b]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Luxembourgish [lb] + //! author : mweimerskirch : https://github.com/mweimerskirch, David Raison : https://github.com/kwisatz + + function lb__processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eng Minutt', 'enger Minutt'], + 'h': ['eng Stonn', 'enger Stonn'], + 'd': ['een Dag', 'engem Dag'], + 'M': ['ee Mount', 'engem Mount'], + 'y': ['ee Joer', 'engem Joer'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; + } + function processFutureTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'a ' + string; + } + return 'an ' + string; + } + function processPastTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'viru ' + string; + } + return 'virun ' + string; + } + /** + * Returns true if the word before the given number loses the '-n' ending. + * e.g. 'an 10 Deeg' but 'a 5 Deeg' + * + * @param number {integer} + * @returns {boolean} + */ + function eifelerRegelAppliesToNumber(number) { + number = parseInt(number, 10); + if (isNaN(number)) { + return false; + } + if (number < 0) { + // Negative Number --> always true + return true; + } else if (number < 10) { + // Only 1 digit + if (4 <= number && number <= 7) { + return true; + } + return false; + } else if (number < 100) { + // 2 digits + var lastDigit = number % 10, firstDigit = number / 10; + if (lastDigit === 0) { + return eifelerRegelAppliesToNumber(firstDigit); + } + return eifelerRegelAppliesToNumber(lastDigit); + } else if (number < 10000) { + // 3 or 4 digits --> recursively check first digit + while (number >= 10) { + number = number / 10; + } + return eifelerRegelAppliesToNumber(number); + } else { + // Anything larger than 4 digits: recursively check first n-3 digits + number = number / 1000; + return eifelerRegelAppliesToNumber(number); + } + } + + var lb = moment.defineLocale('lb', { + months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + monthsParseExact : true, + weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'), + weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'), + weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm [Auer]', + LTS: 'H:mm:ss [Auer]', + L: 'DD.MM.YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm [Auer]', + LLLL: 'dddd, D. MMMM YYYY H:mm [Auer]' + }, + calendar: { + sameDay: '[Haut um] LT', + sameElse: 'L', + nextDay: '[Muer um] LT', + nextWeek: 'dddd [um] LT', + lastDay: '[Gëschter um] LT', + lastWeek: function () { + // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule + switch (this.day()) { + case 2: + case 4: + return '[Leschten] dddd [um] LT'; + default: + return '[Leschte] dddd [um] LT'; + } + } + }, + relativeTime : { + future : processFutureTime, + past : processPastTime, + s : 'e puer Sekonnen', + m : lb__processRelativeTime, + mm : '%d Minutten', + h : lb__processRelativeTime, + hh : '%d Stonnen', + d : lb__processRelativeTime, + dd : '%d Deeg', + M : lb__processRelativeTime, + MM : '%d Méint', + y : lb__processRelativeTime, + yy : '%d Joer' + }, + ordinalParse: /\d{1,2}\./, + ordinal: '%d.', + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Lao [lo] + //! author : Ryan Hart : https://github.com/ryanhart2 + + var lo = moment.defineLocale('lo', { + months : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'), + monthsShort : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'), + weekdays : 'ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'), + weekdaysShort : 'ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'), + weekdaysMin : 'ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'ວັນdddd D MMMM YYYY HH:mm' + }, + meridiemParse: /ຕອນເຊົ້າ|ຕອນແລງ/, + isPM: function (input) { + return input === 'ຕອນແລງ'; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ຕອນເຊົ້າ'; + } else { + return 'ຕອນແລງ'; + } + }, + calendar : { + sameDay : '[ມື້ນີ້ເວລາ] LT', + nextDay : '[ມື້ອື່ນເວລາ] LT', + nextWeek : '[ວັນ]dddd[ໜ້າເວລາ] LT', + lastDay : '[ມື້ວານນີ້ເວລາ] LT', + lastWeek : '[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'ອີກ %s', + past : '%sຜ່ານມາ', + s : 'ບໍ່ເທົ່າໃດວິນາທີ', + m : '1 ນາທີ', + mm : '%d ນາທີ', + h : '1 ຊົ່ວໂມງ', + hh : '%d ຊົ່ວໂມງ', + d : '1 ມື້', + dd : '%d ມື້', + M : '1 ເດືອນ', + MM : '%d ເດືອນ', + y : '1 ປີ', + yy : '%d ປີ' + }, + ordinalParse: /(ທີ່)\d{1,2}/, + ordinal : function (number) { + return 'ທີ່' + number; + } + }); + + //! moment.js locale configuration + //! locale : Lithuanian [lt] + //! author : Mindaugas Mozūras : https://github.com/mmozuras + + var lt__units = { + 'm' : 'minutė_minutės_minutę', + 'mm': 'minutės_minučių_minutes', + 'h' : 'valanda_valandos_valandą', + 'hh': 'valandos_valandų_valandas', + 'd' : 'diena_dienos_dieną', + 'dd': 'dienos_dienų_dienas', + 'M' : 'mėnuo_mėnesio_mėnesį', + 'MM': 'mėnesiai_mėnesių_mėnesius', + 'y' : 'metai_metų_metus', + 'yy': 'metai_metų_metus' + }; + function translateSeconds(number, withoutSuffix, key, isFuture) { + if (withoutSuffix) { + return 'kelios sekundės'; + } else { + return isFuture ? 'kelių sekundžių' : 'kelias sekundes'; + } + } + function translateSingular(number, withoutSuffix, key, isFuture) { + return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]); + } + function special(number) { + return number % 10 === 0 || (number > 10 && number < 20); + } + function forms(key) { + return lt__units[key].split('_'); + } + function lt__translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + if (number === 1) { + return result + translateSingular(number, withoutSuffix, key[0], isFuture); + } else if (withoutSuffix) { + return result + (special(number) ? forms(key)[1] : forms(key)[0]); + } else { + if (isFuture) { + return result + forms(key)[1]; + } else { + return result + (special(number) ? forms(key)[1] : forms(key)[2]); + } + } + } + var lt = moment.defineLocale('lt', { + months : { + format: 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'), + standalone: 'sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis'.split('_'), + isFormat: /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?|MMMM?(\[[^\[\]]*\]|\s+)+D[oD]?/ + }, + monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'), + weekdays : { + format: 'sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį'.split('_'), + standalone: 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_'), + isFormat: /dddd HH:mm/ + }, + weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'), + weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'YYYY [m.] MMMM D [d.]', + LLL : 'YYYY [m.] MMMM D [d.], HH:mm [val.]', + LLLL : 'YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]', + l : 'YYYY-MM-DD', + ll : 'YYYY [m.] MMMM D [d.]', + lll : 'YYYY [m.] MMMM D [d.], HH:mm [val.]', + llll : 'YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]' + }, + calendar : { + sameDay : '[Šiandien] LT', + nextDay : '[Rytoj] LT', + nextWeek : 'dddd LT', + lastDay : '[Vakar] LT', + lastWeek : '[Praėjusį] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : 'po %s', + past : 'prieš %s', + s : translateSeconds, + m : translateSingular, + mm : lt__translate, + h : translateSingular, + hh : lt__translate, + d : translateSingular, + dd : lt__translate, + M : translateSingular, + MM : lt__translate, + y : translateSingular, + yy : lt__translate + }, + ordinalParse: /\d{1,2}-oji/, + ordinal : function (number) { + return number + '-oji'; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Latvian [lv] + //! author : Kristaps Karlsons : https://github.com/skakri + //! author : Jānis Elmeris : https://github.com/JanisE + + var lv__units = { + 'm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'mm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'h': 'stundas_stundām_stunda_stundas'.split('_'), + 'hh': 'stundas_stundām_stunda_stundas'.split('_'), + 'd': 'dienas_dienām_diena_dienas'.split('_'), + 'dd': 'dienas_dienām_diena_dienas'.split('_'), + 'M': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'MM': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'y': 'gada_gadiem_gads_gadi'.split('_'), + 'yy': 'gada_gadiem_gads_gadi'.split('_') + }; + /** + * @param withoutSuffix boolean true = a length of time; false = before/after a period of time. + */ + function format(forms, number, withoutSuffix) { + if (withoutSuffix) { + // E.g. "21 minūte", "3 minūtes". + return number % 10 === 1 && number % 100 !== 11 ? forms[2] : forms[3]; + } else { + // E.g. "21 minūtes" as in "pēc 21 minūtes". + // E.g. "3 minūtēm" as in "pēc 3 minūtēm". + return number % 10 === 1 && number % 100 !== 11 ? forms[0] : forms[1]; + } + } + function lv__relativeTimeWithPlural(number, withoutSuffix, key) { + return number + ' ' + format(lv__units[key], number, withoutSuffix); + } + function relativeTimeWithSingular(number, withoutSuffix, key) { + return format(lv__units[key], number, withoutSuffix); + } + function relativeSeconds(number, withoutSuffix) { + return withoutSuffix ? 'dažas sekundes' : 'dažām sekundēm'; + } + + var lv = moment.defineLocale('lv', { + months : 'janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec'.split('_'), + weekdays : 'svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena'.split('_'), + weekdaysShort : 'Sv_P_O_T_C_Pk_S'.split('_'), + weekdaysMin : 'Sv_P_O_T_C_Pk_S'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY.', + LL : 'YYYY. [gada] D. MMMM', + LLL : 'YYYY. [gada] D. MMMM, HH:mm', + LLLL : 'YYYY. [gada] D. MMMM, dddd, HH:mm' + }, + calendar : { + sameDay : '[Šodien pulksten] LT', + nextDay : '[Rīt pulksten] LT', + nextWeek : 'dddd [pulksten] LT', + lastDay : '[Vakar pulksten] LT', + lastWeek : '[Pagājušā] dddd [pulksten] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'pēc %s', + past : 'pirms %s', + s : relativeSeconds, + m : relativeTimeWithSingular, + mm : lv__relativeTimeWithPlural, + h : relativeTimeWithSingular, + hh : lv__relativeTimeWithPlural, + d : relativeTimeWithSingular, + dd : lv__relativeTimeWithPlural, + M : relativeTimeWithSingular, + MM : lv__relativeTimeWithPlural, + y : relativeTimeWithSingular, + yy : lv__relativeTimeWithPlural + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Montenegrin [me] + //! author : Miodrag Nikač <miodrag@restartit.me> : https://github.com/miodragnikac + + var me__translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jednog minuta'], + mm: ['minut', 'minuta', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mjesec', 'mjeseca', 'mjeseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = me__translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + me__translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var me = moment.defineLocale('me', { + months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'), + monthsParseExact : true, + weekdays: 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort: 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm', + LTS : 'H:mm:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm', + LLLL: 'dddd, D. MMMM YYYY H:mm' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sjutra u] LT', + + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedjelje] [u] LT', + '[prošlog] [ponedjeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srijede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'nekoliko sekundi', + m : me__translator.translate, + mm : me__translator.translate, + h : me__translator.translate, + hh : me__translator.translate, + d : 'dan', + dd : me__translator.translate, + M : 'mjesec', + MM : me__translator.translate, + y : 'godinu', + yy : me__translator.translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Macedonian [mk] + //! author : Borislav Mickov : https://github.com/B0k0 + + var mk = moment.defineLocale('mk', { + months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'), + weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'), + weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'D.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd, D MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[Денес во] LT', + nextDay : '[Утре во] LT', + nextWeek : '[Во] dddd [во] LT', + lastDay : '[Вчера во] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + case 6: + return '[Изминатата] dddd [во] LT'; + case 1: + case 2: + case 4: + case 5: + return '[Изминатиот] dddd [во] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'после %s', + past : 'пред %s', + s : 'неколку секунди', + m : 'минута', + mm : '%d минути', + h : 'час', + hh : '%d часа', + d : 'ден', + dd : '%d дена', + M : 'месец', + MM : '%d месеци', + y : 'година', + yy : '%d години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + ordinal : function (number) { + var lastDigit = number % 10, + last2Digits = number % 100; + if (number === 0) { + return number + '-ев'; + } else if (last2Digits === 0) { + return number + '-ен'; + } else if (last2Digits > 10 && last2Digits < 20) { + return number + '-ти'; + } else if (lastDigit === 1) { + return number + '-ви'; + } else if (lastDigit === 2) { + return number + '-ри'; + } else if (lastDigit === 7 || lastDigit === 8) { + return number + '-ми'; + } else { + return number + '-ти'; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Malayalam [ml] + //! author : Floyd Pink : https://github.com/floydpink + + var ml = moment.defineLocale('ml', { + months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'), + monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'), + monthsParseExact : true, + weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'), + weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'), + weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'), + longDateFormat : { + LT : 'A h:mm -നു', + LTS : 'A h:mm:ss -നു', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm -നു', + LLLL : 'dddd, D MMMM YYYY, A h:mm -നു' + }, + calendar : { + sameDay : '[ഇന്ന്] LT', + nextDay : '[നാളെ] LT', + nextWeek : 'dddd, LT', + lastDay : '[ഇന്നലെ] LT', + lastWeek : '[കഴിഞ്ഞ] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s കഴിഞ്ഞ്', + past : '%s മുൻപ്', + s : 'അൽപ നിമിഷങ്ങൾ', + m : 'ഒരു മിനിറ്റ്', + mm : '%d മിനിറ്റ്', + h : 'ഒരു മണിക്കൂർ', + hh : '%d മണിക്കൂർ', + d : 'ഒരു ദിവസം', + dd : '%d ദിവസം', + M : 'ഒരു മാസം', + MM : '%d മാസം', + y : 'ഒരു വർഷം', + yy : '%d വർഷം' + }, + meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if ((meridiem === 'രാത്രി' && hour >= 4) || + meridiem === 'ഉച്ച കഴിഞ്ഞ്' || + meridiem === 'വൈകുന്നേരം') { + return hour + 12; + } else { + return hour; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'രാത്രി'; + } else if (hour < 12) { + return 'രാവിലെ'; + } else if (hour < 17) { + return 'ഉച്ച കഴിഞ്ഞ്'; + } else if (hour < 20) { + return 'വൈകുന്നേരം'; + } else { + return 'രാത്രി'; + } + } + }); + + //! moment.js locale configuration + //! locale : Marathi [mr] + //! author : Harshad Kale : https://github.com/kalehv + //! author : Vivek Athalye : https://github.com/vnathalye + + var mr__symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + mr__numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + function relativeTimeMr(number, withoutSuffix, string, isFuture) + { + var output = ''; + if (withoutSuffix) { + switch (string) { + case 's': output = 'काही सेकंद'; break; + case 'm': output = 'एक मिनिट'; break; + case 'mm': output = '%d मिनिटे'; break; + case 'h': output = 'एक तास'; break; + case 'hh': output = '%d तास'; break; + case 'd': output = 'एक दिवस'; break; + case 'dd': output = '%d दिवस'; break; + case 'M': output = 'एक महिना'; break; + case 'MM': output = '%d महिने'; break; + case 'y': output = 'एक वर्ष'; break; + case 'yy': output = '%d वर्षे'; break; + } + } + else { + switch (string) { + case 's': output = 'काही सेकंदां'; break; + case 'm': output = 'एका मिनिटा'; break; + case 'mm': output = '%d मिनिटां'; break; + case 'h': output = 'एका तासा'; break; + case 'hh': output = '%d तासां'; break; + case 'd': output = 'एका दिवसा'; break; + case 'dd': output = '%d दिवसां'; break; + case 'M': output = 'एका महिन्या'; break; + case 'MM': output = '%d महिन्यां'; break; + case 'y': output = 'एका वर्षा'; break; + case 'yy': output = '%d वर्षां'; break; + } + } + return output.replace(/%d/i, number); + } + + var mr = moment.defineLocale('mr', { + months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'), + monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'), + monthsParseExact : true, + weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm वाजता', + LTS : 'A h:mm:ss वाजता', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm वाजता', + LLLL : 'dddd, D MMMM YYYY, A h:mm वाजता' + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[उद्या] LT', + nextWeek : 'dddd, LT', + lastDay : '[काल] LT', + lastWeek: '[मागील] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future: '%sमध्ये', + past: '%sपूर्वी', + s: relativeTimeMr, + m: relativeTimeMr, + mm: relativeTimeMr, + h: relativeTimeMr, + hh: relativeTimeMr, + d: relativeTimeMr, + dd: relativeTimeMr, + M: relativeTimeMr, + MM: relativeTimeMr, + y: relativeTimeMr, + yy: relativeTimeMr + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return mr__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return mr__symbolMap[match]; + }); + }, + meridiemParse: /रात्री|सकाळी|दुपारी|सायंकाळी/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात्री') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सकाळी') { + return hour; + } else if (meridiem === 'दुपारी') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'सायंकाळी') { + return hour + 12; + } + }, + meridiem: function (hour, minute, isLower) { + if (hour < 4) { + return 'रात्री'; + } else if (hour < 10) { + return 'सकाळी'; + } else if (hour < 17) { + return 'दुपारी'; + } else if (hour < 20) { + return 'सायंकाळी'; + } else { + return 'रात्री'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Malay [ms-my] + //! note : DEPRECATED, the correct one is [ms] + //! author : Weldan Jamili : https://github.com/weldan + + var ms_my = moment.defineLocale('ms-my', { + months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'), + monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'), + weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'), + weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'), + weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /pagi|tengahari|petang|malam/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'tengahari') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'petang' || meridiem === 'malam') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'tengahari'; + } else if (hours < 19) { + return 'petang'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Esok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kelmarin pukul] LT', + lastWeek : 'dddd [lepas pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'dalam %s', + past : '%s yang lepas', + s : 'beberapa saat', + m : 'seminit', + mm : '%d minit', + h : 'sejam', + hh : '%d jam', + d : 'sehari', + dd : '%d hari', + M : 'sebulan', + MM : '%d bulan', + y : 'setahun', + yy : '%d tahun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Malay [ms] + //! author : Weldan Jamili : https://github.com/weldan + + var ms = moment.defineLocale('ms', { + months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'), + monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'), + weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'), + weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'), + weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /pagi|tengahari|petang|malam/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'tengahari') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'petang' || meridiem === 'malam') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'tengahari'; + } else if (hours < 19) { + return 'petang'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Esok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kelmarin pukul] LT', + lastWeek : 'dddd [lepas pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'dalam %s', + past : '%s yang lepas', + s : 'beberapa saat', + m : 'seminit', + mm : '%d minit', + h : 'sejam', + hh : '%d jam', + d : 'sehari', + dd : '%d hari', + M : 'sebulan', + MM : '%d bulan', + y : 'setahun', + yy : '%d tahun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Burmese [my] + //! author : Squar team, mysquar.com + + var my__symbolMap = { + '1': '၁', + '2': '၂', + '3': '၃', + '4': '၄', + '5': '၅', + '6': '၆', + '7': '၇', + '8': '၈', + '9': '၉', + '0': '၀' + }, my__numberMap = { + '၁': '1', + '၂': '2', + '၃': '3', + '၄': '4', + '၅': '5', + '၆': '6', + '၇': '7', + '၈': '8', + '၉': '9', + '၀': '0' + }; + + var my = moment.defineLocale('my', { + months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'), + monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'), + weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'), + weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + + longDateFormat: { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[ယနေ.] LT [မှာ]', + nextDay: '[မနက်ဖြန်] LT [မှာ]', + nextWeek: 'dddd LT [မှာ]', + lastDay: '[မနေ.က] LT [မှာ]', + lastWeek: '[ပြီးခဲ့သော] dddd LT [မှာ]', + sameElse: 'L' + }, + relativeTime: { + future: 'လာမည့် %s မှာ', + past: 'လွန်ခဲ့သော %s က', + s: 'စက္ကန်.အနည်းငယ်', + m: 'တစ်မိနစ်', + mm: '%d မိနစ်', + h: 'တစ်နာရီ', + hh: '%d နာရီ', + d: 'တစ်ရက်', + dd: '%d ရက်', + M: 'တစ်လ', + MM: '%d လ', + y: 'တစ်နှစ်', + yy: '%d နှစ်' + }, + preparse: function (string) { + return string.replace(/[၁၂၃၄၅၆၇၈၉၀]/g, function (match) { + return my__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return my__symbolMap[match]; + }); + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Norwegian Bokmål [nb] + //! authors : Espen Hovlandsdal : https://github.com/rexxars + //! Sigurd Gartmann : https://github.com/sigurdga + + var nb = moment.defineLocale('nb', { + months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.'.split('_'), + monthsParseExact : true, + weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'), + weekdaysShort : 'sø._ma._ti._on._to._fr._lø.'.split('_'), + weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] HH:mm', + LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm' + }, + calendar : { + sameDay: '[i dag kl.] LT', + nextDay: '[i morgen kl.] LT', + nextWeek: 'dddd [kl.] LT', + lastDay: '[i går kl.] LT', + lastWeek: '[forrige] dddd [kl.] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : '%s siden', + s : 'noen sekunder', + m : 'ett minutt', + mm : '%d minutter', + h : 'en time', + hh : '%d timer', + d : 'en dag', + dd : '%d dager', + M : 'en måned', + MM : '%d måneder', + y : 'ett år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Nepalese [ne] + //! author : suvash : https://github.com/suvash + + var ne__symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + ne__numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var ne = moment.defineLocale('ne', { + months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'), + monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'), + monthsParseExact : true, + weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'), + weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'), + weekdaysMin : 'आ._सो._मं._बु._बि._शु._श.'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'Aको h:mm बजे', + LTS : 'Aको h:mm:ss बजे', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, Aको h:mm बजे', + LLLL : 'dddd, D MMMM YYYY, Aको h:mm बजे' + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return ne__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return ne__symbolMap[match]; + }); + }, + meridiemParse: /राति|बिहान|दिउँसो|साँझ/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'राति') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'बिहान') { + return hour; + } else if (meridiem === 'दिउँसो') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'साँझ') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 3) { + return 'राति'; + } else if (hour < 12) { + return 'बिहान'; + } else if (hour < 16) { + return 'दिउँसो'; + } else if (hour < 20) { + return 'साँझ'; + } else { + return 'राति'; + } + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[भोलि] LT', + nextWeek : '[आउँदो] dddd[,] LT', + lastDay : '[हिजो] LT', + lastWeek : '[गएको] dddd[,] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%sमा', + past : '%s अगाडि', + s : 'केही क्षण', + m : 'एक मिनेट', + mm : '%d मिनेट', + h : 'एक घण्टा', + hh : '%d घण्टा', + d : 'एक दिन', + dd : '%d दिन', + M : 'एक महिना', + MM : '%d महिना', + y : 'एक बर्ष', + yy : '%d बर्ष' + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Dutch [nl] + //! author : Joris Röling : https://github.com/jjupiter + + var nl__monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_'), + nl__monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_'); + + var nl = moment.defineLocale('nl', { + months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return nl__monthsShortWithoutDots[m.month()]; + } else { + return nl__monthsShortWithDots[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'), + weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'), + weekdaysMin : 'Zo_Ma_Di_Wo_Do_Vr_Za'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[vandaag om] LT', + nextDay: '[morgen om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[gisteren om] LT', + lastWeek: '[afgelopen] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'over %s', + past : '%s geleden', + s : 'een paar seconden', + m : 'één minuut', + mm : '%d minuten', + h : 'één uur', + hh : '%d uur', + d : 'één dag', + dd : '%d dagen', + M : 'één maand', + MM : '%d maanden', + y : 'één jaar', + yy : '%d jaar' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Nynorsk [nn] + //! author : https://github.com/mechuwind + + var nn = moment.defineLocale('nn', { + months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), + weekdays : 'sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag'.split('_'), + weekdaysShort : 'sun_mån_tys_ons_tor_fre_lau'.split('_'), + weekdaysMin : 'su_må_ty_on_to_fr_lø'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] H:mm', + LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm' + }, + calendar : { + sameDay: '[I dag klokka] LT', + nextDay: '[I morgon klokka] LT', + nextWeek: 'dddd [klokka] LT', + lastDay: '[I går klokka] LT', + lastWeek: '[Føregåande] dddd [klokka] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : '%s sidan', + s : 'nokre sekund', + m : 'eit minutt', + mm : '%d minutt', + h : 'ein time', + hh : '%d timar', + d : 'ein dag', + dd : '%d dagar', + M : 'ein månad', + MM : '%d månader', + y : 'eit år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Punjabi (India) [pa-in] + //! author : Harpreet Singh : https://github.com/harpreetkhalsagtbit + + var pa_in__symbolMap = { + '1': '੧', + '2': '੨', + '3': '੩', + '4': '੪', + '5': '੫', + '6': '੬', + '7': '੭', + '8': '੮', + '9': '੯', + '0': '੦' + }, + pa_in__numberMap = { + '੧': '1', + '੨': '2', + '੩': '3', + '੪': '4', + '੫': '5', + '੬': '6', + '੭': '7', + '੮': '8', + '੯': '9', + '੦': '0' + }; + + var pa_in = moment.defineLocale('pa-in', { + // There are months name as per Nanakshahi Calender but they are not used as rigidly in modern Punjabi. + months : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'), + monthsShort : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'), + weekdays : 'ਐਤਵਾਰ_ਸੋਮਵਾਰ_ਮੰਗਲਵਾਰ_ਬੁਧਵਾਰ_ਵੀਰਵਾਰ_ਸ਼ੁੱਕਰਵਾਰ_ਸ਼ਨੀਚਰਵਾਰ'.split('_'), + weekdaysShort : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'), + weekdaysMin : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'), + longDateFormat : { + LT : 'A h:mm ਵਜੇ', + LTS : 'A h:mm:ss ਵਜੇ', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm ਵਜੇ', + LLLL : 'dddd, D MMMM YYYY, A h:mm ਵਜੇ' + }, + calendar : { + sameDay : '[ਅਜ] LT', + nextDay : '[ਕਲ] LT', + nextWeek : 'dddd, LT', + lastDay : '[ਕਲ] LT', + lastWeek : '[ਪਿਛਲੇ] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ਵਿੱਚ', + past : '%s ਪਿਛਲੇ', + s : 'ਕੁਝ ਸਕਿੰਟ', + m : 'ਇਕ ਮਿੰਟ', + mm : '%d ਮਿੰਟ', + h : 'ਇੱਕ ਘੰਟਾ', + hh : '%d ਘੰਟੇ', + d : 'ਇੱਕ ਦਿਨ', + dd : '%d ਦਿਨ', + M : 'ਇੱਕ ਮਹੀਨਾ', + MM : '%d ਮਹੀਨੇ', + y : 'ਇੱਕ ਸਾਲ', + yy : '%d ਸਾਲ' + }, + preparse: function (string) { + return string.replace(/[੧੨੩੪੫੬੭੮੯੦]/g, function (match) { + return pa_in__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return pa_in__symbolMap[match]; + }); + }, + // Punjabi notation for meridiems are quite fuzzy in practice. While there exists + // a rigid notion of a 'Pahar' it is not used as rigidly in modern Punjabi. + meridiemParse: /ਰਾਤ|ਸਵੇਰ|ਦੁਪਹਿਰ|ਸ਼ਾਮ/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'ਰਾਤ') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'ਸਵੇਰ') { + return hour; + } else if (meridiem === 'ਦੁਪਹਿਰ') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'ਸ਼ਾਮ') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ਰਾਤ'; + } else if (hour < 10) { + return 'ਸਵੇਰ'; + } else if (hour < 17) { + return 'ਦੁਪਹਿਰ'; + } else if (hour < 20) { + return 'ਸ਼ਾਮ'; + } else { + return 'ਰਾਤ'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Polish [pl] + //! author : Rafal Hirsz : https://github.com/evoL + + var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split('_'), + monthsSubjective = 'stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia'.split('_'); + function pl__plural(n) { + return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1); + } + function pl__translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'minuta' : 'minutę'; + case 'mm': + return result + (pl__plural(number) ? 'minuty' : 'minut'); + case 'h': + return withoutSuffix ? 'godzina' : 'godzinę'; + case 'hh': + return result + (pl__plural(number) ? 'godziny' : 'godzin'); + case 'MM': + return result + (pl__plural(number) ? 'miesiące' : 'miesięcy'); + case 'yy': + return result + (pl__plural(number) ? 'lata' : 'lat'); + } + } + + var pl = moment.defineLocale('pl', { + months : function (momentToFormat, format) { + if (format === '') { + // Hack: if format empty we know this is used to generate + // RegExp by moment. Give then back both valid forms of months + // in RegExp ready format. + return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')'; + } else if (/D MMMM/.test(format)) { + return monthsSubjective[momentToFormat.month()]; + } else { + return monthsNominative[momentToFormat.month()]; + } + }, + monthsShort : 'sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru'.split('_'), + weekdays : 'niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota'.split('_'), + weekdaysShort : 'nie_pon_wt_śr_czw_pt_sb'.split('_'), + weekdaysMin : 'Nd_Pn_Wt_Śr_Cz_Pt_So'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Dziś o] LT', + nextDay: '[Jutro o] LT', + nextWeek: '[W] dddd [o] LT', + lastDay: '[Wczoraj o] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[W zeszłą niedzielę o] LT'; + case 3: + return '[W zeszłą środę o] LT'; + case 6: + return '[W zeszłą sobotę o] LT'; + default: + return '[W zeszły] dddd [o] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'za %s', + past : '%s temu', + s : 'kilka sekund', + m : pl__translate, + mm : pl__translate, + h : pl__translate, + hh : pl__translate, + d : '1 dzień', + dd : '%d dni', + M : 'miesiąc', + MM : pl__translate, + y : 'rok', + yy : pl__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Portuguese (Brazil) [pt-br] + //! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira + + var pt_br = moment.defineLocale('pt-br', { + months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'), + monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'), + weekdays : 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split('_'), + weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'), + weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY [às] HH:mm', + LLLL : 'dddd, D [de] MMMM [de] YYYY [às] HH:mm' + }, + calendar : { + sameDay: '[Hoje às] LT', + nextDay: '[Amanhã às] LT', + nextWeek: 'dddd [às] LT', + lastDay: '[Ontem às] LT', + lastWeek: function () { + return (this.day() === 0 || this.day() === 6) ? + '[Último] dddd [às] LT' : // Saturday + Sunday + '[Última] dddd [às] LT'; // Monday - Friday + }, + sameElse: 'L' + }, + relativeTime : { + future : 'em %s', + past : '%s atrás', + s : 'poucos segundos', + m : 'um minuto', + mm : '%d minutos', + h : 'uma hora', + hh : '%d horas', + d : 'um dia', + dd : '%d dias', + M : 'um mês', + MM : '%d meses', + y : 'um ano', + yy : '%d anos' + }, + ordinalParse: /\d{1,2}º/, + ordinal : '%dº' + }); + + //! moment.js locale configuration + //! locale : Portuguese [pt] + //! author : Jefferson : https://github.com/jalex79 + + var pt = moment.defineLocale('pt', { + months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'), + monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'), + weekdays : 'Domingo_Segunda-Feira_Terça-Feira_Quarta-Feira_Quinta-Feira_Sexta-Feira_Sábado'.split('_'), + weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'), + weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY HH:mm', + LLLL : 'dddd, D [de] MMMM [de] YYYY HH:mm' + }, + calendar : { + sameDay: '[Hoje às] LT', + nextDay: '[Amanhã às] LT', + nextWeek: 'dddd [às] LT', + lastDay: '[Ontem às] LT', + lastWeek: function () { + return (this.day() === 0 || this.day() === 6) ? + '[Último] dddd [às] LT' : // Saturday + Sunday + '[Última] dddd [às] LT'; // Monday - Friday + }, + sameElse: 'L' + }, + relativeTime : { + future : 'em %s', + past : 'há %s', + s : 'segundos', + m : 'um minuto', + mm : '%d minutos', + h : 'uma hora', + hh : '%d horas', + d : 'um dia', + dd : '%d dias', + M : 'um mês', + MM : '%d meses', + y : 'um ano', + yy : '%d anos' + }, + ordinalParse: /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Romanian [ro] + //! author : Vlad Gurdiga : https://github.com/gurdiga + //! author : Valentin Agachi : https://github.com/avaly + + function ro__relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': 'minute', + 'hh': 'ore', + 'dd': 'zile', + 'MM': 'luni', + 'yy': 'ani' + }, + separator = ' '; + if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) { + separator = ' de '; + } + return number + separator + format[key]; + } + + var ro = moment.defineLocale('ro', { + months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'), + monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays : 'duminică_luni_marți_miercuri_joi_vineri_sâmbătă'.split('_'), + weekdaysShort : 'Dum_Lun_Mar_Mie_Joi_Vin_Sâm'.split('_'), + weekdaysMin : 'Du_Lu_Ma_Mi_Jo_Vi_Sâ'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd, D MMMM YYYY H:mm' + }, + calendar : { + sameDay: '[azi la] LT', + nextDay: '[mâine la] LT', + nextWeek: 'dddd [la] LT', + lastDay: '[ieri la] LT', + lastWeek: '[fosta] dddd [la] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'peste %s', + past : '%s în urmă', + s : 'câteva secunde', + m : 'un minut', + mm : ro__relativeTimeWithPlural, + h : 'o oră', + hh : ro__relativeTimeWithPlural, + d : 'o zi', + dd : ro__relativeTimeWithPlural, + M : 'o lună', + MM : ro__relativeTimeWithPlural, + y : 'un an', + yy : ro__relativeTimeWithPlural + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Russian [ru] + //! author : Viktorminator : https://github.com/Viktorminator + //! Author : Menelion Elensúle : https://github.com/Oire + //! author : Коренберг Марк : https://github.com/socketpair + + function ru__plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); + } + function ru__relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут', + 'hh': 'час_часа_часов', + 'dd': 'день_дня_дней', + 'MM': 'месяц_месяца_месяцев', + 'yy': 'год_года_лет' + }; + if (key === 'm') { + return withoutSuffix ? 'минута' : 'минуту'; + } + else { + return number + ' ' + ru__plural(format[key], +number); + } + } + var monthsParse = [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[йя]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i]; + + // http://new.gramota.ru/spravka/rules/139-prop : § 103 + // Сокращения месяцев: http://new.gramota.ru/spravka/buro/search-answer?s=242637 + // CLDR data: http://www.unicode.org/cldr/charts/28/summary/ru.html#1753 + var ru = moment.defineLocale('ru', { + months : { + format: 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_'), + standalone: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_') + }, + monthsShort : { + // по CLDR именно "июл." и "июн.", но какой смысл менять букву на точку ? + format: 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split('_'), + standalone: 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split('_') + }, + weekdays : { + standalone: 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'), + format: 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_'), + isFormat: /\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/ + }, + weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + monthsParse : monthsParse, + longMonthsParse : monthsParse, + shortMonthsParse : monthsParse, + + // полные названия с падежами, по три буквы, для некоторых, по 4 буквы, сокращения с точкой и без точки + monthsRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i, + + // копия предыдущего + monthsShortRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i, + + // полные названия с падежами + monthsStrictRegex: /^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i, + + // Выражение, которое соотвествует только сокращённым формам + monthsShortStrictRegex: /^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY г.', + LLL : 'D MMMM YYYY г., HH:mm', + LLLL : 'dddd, D MMMM YYYY г., HH:mm' + }, + calendar : { + sameDay: '[Сегодня в] LT', + nextDay: '[Завтра в] LT', + lastDay: '[Вчера в] LT', + nextWeek: function (now) { + if (now.week() !== this.week()) { + switch (this.day()) { + case 0: + return '[В следующее] dddd [в] LT'; + case 1: + case 2: + case 4: + return '[В следующий] dddd [в] LT'; + case 3: + case 5: + case 6: + return '[В следующую] dddd [в] LT'; + } + } else { + if (this.day() === 2) { + return '[Во] dddd [в] LT'; + } else { + return '[В] dddd [в] LT'; + } + } + }, + lastWeek: function (now) { + if (now.week() !== this.week()) { + switch (this.day()) { + case 0: + return '[В прошлое] dddd [в] LT'; + case 1: + case 2: + case 4: + return '[В прошлый] dddd [в] LT'; + case 3: + case 5: + case 6: + return '[В прошлую] dddd [в] LT'; + } + } else { + if (this.day() === 2) { + return '[Во] dddd [в] LT'; + } else { + return '[В] dddd [в] LT'; + } + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'через %s', + past : '%s назад', + s : 'несколько секунд', + m : ru__relativeTimeWithPlural, + mm : ru__relativeTimeWithPlural, + h : 'час', + hh : ru__relativeTimeWithPlural, + d : 'день', + dd : ru__relativeTimeWithPlural, + M : 'месяц', + MM : ru__relativeTimeWithPlural, + y : 'год', + yy : ru__relativeTimeWithPlural + }, + meridiemParse: /ночи|утра|дня|вечера/i, + isPM : function (input) { + return /^(дня|вечера)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночи'; + } else if (hour < 12) { + return 'утра'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечера'; + } + }, + ordinalParse: /\d{1,2}-(й|го|я)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + return number + '-й'; + case 'D': + return number + '-го'; + case 'w': + case 'W': + return number + '-я'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Northern Sami [se] + //! authors : Bård Rolstad Henriksen : https://github.com/karamell + + + var se = moment.defineLocale('se', { + months : 'ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu'.split('_'), + monthsShort : 'ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov'.split('_'), + weekdays : 'sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat'.split('_'), + weekdaysShort : 'sotn_vuos_maŋ_gask_duor_bear_láv'.split('_'), + weekdaysMin : 's_v_m_g_d_b_L'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'MMMM D. [b.] YYYY', + LLL : 'MMMM D. [b.] YYYY [ti.] HH:mm', + LLLL : 'dddd, MMMM D. [b.] YYYY [ti.] HH:mm' + }, + calendar : { + sameDay: '[otne ti] LT', + nextDay: '[ihttin ti] LT', + nextWeek: 'dddd [ti] LT', + lastDay: '[ikte ti] LT', + lastWeek: '[ovddit] dddd [ti] LT', + sameElse: 'L' + }, + relativeTime : { + future : '%s geažes', + past : 'maŋit %s', + s : 'moadde sekunddat', + m : 'okta minuhta', + mm : '%d minuhtat', + h : 'okta diimmu', + hh : '%d diimmut', + d : 'okta beaivi', + dd : '%d beaivvit', + M : 'okta mánnu', + MM : '%d mánut', + y : 'okta jahki', + yy : '%d jagit' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Sinhalese [si] + //! author : Sampath Sitinamaluwa : https://github.com/sampathsris + + /*jshint -W100*/ + var si = moment.defineLocale('si', { + months : 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split('_'), + monthsShort : 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split('_'), + weekdays : 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split('_'), + weekdaysShort : 'ඉරි_සඳු_අඟ_බදා_බ්රහ_සිකු_සෙන'.split('_'), + weekdaysMin : 'ඉ_ස_අ_බ_බ්ර_සි_සෙ'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'a h:mm', + LTS : 'a h:mm:ss', + L : 'YYYY/MM/DD', + LL : 'YYYY MMMM D', + LLL : 'YYYY MMMM D, a h:mm', + LLLL : 'YYYY MMMM D [වැනි] dddd, a h:mm:ss' + }, + calendar : { + sameDay : '[අද] LT[ට]', + nextDay : '[හෙට] LT[ට]', + nextWeek : 'dddd LT[ට]', + lastDay : '[ඊයේ] LT[ට]', + lastWeek : '[පසුගිය] dddd LT[ට]', + sameElse : 'L' + }, + relativeTime : { + future : '%sකින්', + past : '%sකට පෙර', + s : 'තත්පර කිහිපය', + m : 'මිනිත්තුව', + mm : 'මිනිත්තු %d', + h : 'පැය', + hh : 'පැය %d', + d : 'දිනය', + dd : 'දින %d', + M : 'මාසය', + MM : 'මාස %d', + y : 'වසර', + yy : 'වසර %d' + }, + ordinalParse: /\d{1,2} වැනි/, + ordinal : function (number) { + return number + ' වැනි'; + }, + meridiemParse : /පෙර වරු|පස් වරු|පෙ.ව|ප.ව./, + isPM : function (input) { + return input === 'ප.ව.' || input === 'පස් වරු'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'ප.ව.' : 'පස් වරු'; + } else { + return isLower ? 'පෙ.ව.' : 'පෙර වරු'; + } + } + }); + + //! moment.js locale configuration + //! locale : Slovak [sk] + //! author : Martin Minka : https://github.com/k2s + //! based on work of petrbela : https://github.com/petrbela + + var sk__months = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_'), + sk__monthsShort = 'jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec'.split('_'); + function sk__plural(n) { + return (n > 1) && (n < 5); + } + function sk__translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': // a few seconds / in a few seconds / a few seconds ago + return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami'; + case 'm': // a minute / in a minute / a minute ago + return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou'); + case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago + if (withoutSuffix || isFuture) { + return result + (sk__plural(number) ? 'minúty' : 'minút'); + } else { + return result + 'minútami'; + } + break; + case 'h': // an hour / in an hour / an hour ago + return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou'); + case 'hh': // 9 hours / in 9 hours / 9 hours ago + if (withoutSuffix || isFuture) { + return result + (sk__plural(number) ? 'hodiny' : 'hodín'); + } else { + return result + 'hodinami'; + } + break; + case 'd': // a day / in a day / a day ago + return (withoutSuffix || isFuture) ? 'deň' : 'dňom'; + case 'dd': // 9 days / in 9 days / 9 days ago + if (withoutSuffix || isFuture) { + return result + (sk__plural(number) ? 'dni' : 'dní'); + } else { + return result + 'dňami'; + } + break; + case 'M': // a month / in a month / a month ago + return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom'; + case 'MM': // 9 months / in 9 months / 9 months ago + if (withoutSuffix || isFuture) { + return result + (sk__plural(number) ? 'mesiace' : 'mesiacov'); + } else { + return result + 'mesiacmi'; + } + break; + case 'y': // a year / in a year / a year ago + return (withoutSuffix || isFuture) ? 'rok' : 'rokom'; + case 'yy': // 9 years / in 9 years / 9 years ago + if (withoutSuffix || isFuture) { + return result + (sk__plural(number) ? 'roky' : 'rokov'); + } else { + return result + 'rokmi'; + } + break; + } + } + + var sk = moment.defineLocale('sk', { + months : sk__months, + monthsShort : sk__monthsShort, + weekdays : 'nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota'.split('_'), + weekdaysShort : 'ne_po_ut_st_št_pi_so'.split('_'), + weekdaysMin : 'ne_po_ut_st_št_pi_so'.split('_'), + longDateFormat : { + LT: 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd D. MMMM YYYY H:mm' + }, + calendar : { + sameDay: '[dnes o] LT', + nextDay: '[zajtra o] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[v nedeľu o] LT'; + case 1: + case 2: + return '[v] dddd [o] LT'; + case 3: + return '[v stredu o] LT'; + case 4: + return '[vo štvrtok o] LT'; + case 5: + return '[v piatok o] LT'; + case 6: + return '[v sobotu o] LT'; + } + }, + lastDay: '[včera o] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[minulú nedeľu o] LT'; + case 1: + case 2: + return '[minulý] dddd [o] LT'; + case 3: + return '[minulú stredu o] LT'; + case 4: + case 5: + return '[minulý] dddd [o] LT'; + case 6: + return '[minulú sobotu o] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'za %s', + past : 'pred %s', + s : sk__translate, + m : sk__translate, + mm : sk__translate, + h : sk__translate, + hh : sk__translate, + d : sk__translate, + dd : sk__translate, + M : sk__translate, + MM : sk__translate, + y : sk__translate, + yy : sk__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Slovenian [sl] + //! author : Robert Sedovšek : https://github.com/sedovsek + + function sl__processRelativeTime(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nekaj sekund' : 'nekaj sekundami'; + case 'm': + return withoutSuffix ? 'ena minuta' : 'eno minuto'; + case 'mm': + if (number === 1) { + result += withoutSuffix ? 'minuta' : 'minuto'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'minuti' : 'minutama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'minute' : 'minutami'; + } else { + result += withoutSuffix || isFuture ? 'minut' : 'minutami'; + } + return result; + case 'h': + return withoutSuffix ? 'ena ura' : 'eno uro'; + case 'hh': + if (number === 1) { + result += withoutSuffix ? 'ura' : 'uro'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'uri' : 'urama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'ure' : 'urami'; + } else { + result += withoutSuffix || isFuture ? 'ur' : 'urami'; + } + return result; + case 'd': + return withoutSuffix || isFuture ? 'en dan' : 'enim dnem'; + case 'dd': + if (number === 1) { + result += withoutSuffix || isFuture ? 'dan' : 'dnem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'dni' : 'dnevoma'; + } else { + result += withoutSuffix || isFuture ? 'dni' : 'dnevi'; + } + return result; + case 'M': + return withoutSuffix || isFuture ? 'en mesec' : 'enim mesecem'; + case 'MM': + if (number === 1) { + result += withoutSuffix || isFuture ? 'mesec' : 'mesecem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'meseca' : 'mesecema'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'mesece' : 'meseci'; + } else { + result += withoutSuffix || isFuture ? 'mesecev' : 'meseci'; + } + return result; + case 'y': + return withoutSuffix || isFuture ? 'eno leto' : 'enim letom'; + case 'yy': + if (number === 1) { + result += withoutSuffix || isFuture ? 'leto' : 'letom'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'leti' : 'letoma'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'leta' : 'leti'; + } else { + result += withoutSuffix || isFuture ? 'let' : 'leti'; + } + return result; + } + } + + var sl = moment.defineLocale('sl', { + months : 'januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december'.split('_'), + monthsShort : 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays : 'nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota'.split('_'), + weekdaysShort : 'ned._pon._tor._sre._čet._pet._sob.'.split('_'), + weekdaysMin : 'ne_po_to_sr_če_pe_so'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[danes ob] LT', + nextDay : '[jutri ob] LT', + + nextWeek : function () { + switch (this.day()) { + case 0: + return '[v] [nedeljo] [ob] LT'; + case 3: + return '[v] [sredo] [ob] LT'; + case 6: + return '[v] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[v] dddd [ob] LT'; + } + }, + lastDay : '[včeraj ob] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + return '[prejšnjo] [nedeljo] [ob] LT'; + case 3: + return '[prejšnjo] [sredo] [ob] LT'; + case 6: + return '[prejšnjo] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prejšnji] dddd [ob] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'čez %s', + past : 'pred %s', + s : sl__processRelativeTime, + m : sl__processRelativeTime, + mm : sl__processRelativeTime, + h : sl__processRelativeTime, + hh : sl__processRelativeTime, + d : sl__processRelativeTime, + dd : sl__processRelativeTime, + M : sl__processRelativeTime, + MM : sl__processRelativeTime, + y : sl__processRelativeTime, + yy : sl__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Albanian [sq] + //! author : Flakërim Ismani : https://github.com/flakerimi + //! author: Menelion Elensúle: https://github.com/Oire (tests) + //! author : Oerd Cukalla : https://github.com/oerd (fixes) + + var sq = moment.defineLocale('sq', { + months : 'Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor'.split('_'), + monthsShort : 'Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj'.split('_'), + weekdays : 'E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë'.split('_'), + weekdaysShort : 'Die_Hën_Mar_Mër_Enj_Pre_Sht'.split('_'), + weekdaysMin : 'D_H_Ma_Më_E_P_Sh'.split('_'), + weekdaysParseExact : true, + meridiemParse: /PD|MD/, + isPM: function (input) { + return input.charAt(0) === 'M'; + }, + meridiem : function (hours, minutes, isLower) { + return hours < 12 ? 'PD' : 'MD'; + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Sot në] LT', + nextDay : '[Nesër në] LT', + nextWeek : 'dddd [në] LT', + lastDay : '[Dje në] LT', + lastWeek : 'dddd [e kaluar në] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'në %s', + past : '%s më parë', + s : 'disa sekonda', + m : 'një minutë', + mm : '%d minuta', + h : 'një orë', + hh : '%d orë', + d : 'një ditë', + dd : '%d ditë', + M : 'një muaj', + MM : '%d muaj', + y : 'një vit', + yy : '%d vite' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Serbian Cyrillic [sr-cyrl] + //! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j + + var sr_cyrl__translator = { + words: { //Different grammatical cases + m: ['један минут', 'једне минуте'], + mm: ['минут', 'минуте', 'минута'], + h: ['један сат', 'једног сата'], + hh: ['сат', 'сата', 'сати'], + dd: ['дан', 'дана', 'дана'], + MM: ['месец', 'месеца', 'месеци'], + yy: ['година', 'године', 'година'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = sr_cyrl__translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + sr_cyrl__translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var sr_cyrl = moment.defineLocale('sr-cyrl', { + months: 'јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар'.split('_'), + monthsShort: 'јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.'.split('_'), + monthsParseExact: true, + weekdays: 'недеља_понедељак_уторак_среда_четвртак_петак_субота'.split('_'), + weekdaysShort: 'нед._пон._уто._сре._чет._пет._суб.'.split('_'), + weekdaysMin: 'не_по_ут_ср_че_пе_су'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm', + LTS : 'H:mm:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm', + LLLL: 'dddd, D. MMMM YYYY H:mm' + }, + calendar: { + sameDay: '[данас у] LT', + nextDay: '[сутра у] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[у] [недељу] [у] LT'; + case 3: + return '[у] [среду] [у] LT'; + case 6: + return '[у] [суботу] [у] LT'; + case 1: + case 2: + case 4: + case 5: + return '[у] dddd [у] LT'; + } + }, + lastDay : '[јуче у] LT', + lastWeek : function () { + var lastWeekDays = [ + '[прошле] [недеље] [у] LT', + '[прошлог] [понедељка] [у] LT', + '[прошлог] [уторка] [у] LT', + '[прошле] [среде] [у] LT', + '[прошлог] [четвртка] [у] LT', + '[прошлог] [петка] [у] LT', + '[прошле] [суботе] [у] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'за %s', + past : 'пре %s', + s : 'неколико секунди', + m : sr_cyrl__translator.translate, + mm : sr_cyrl__translator.translate, + h : sr_cyrl__translator.translate, + hh : sr_cyrl__translator.translate, + d : 'дан', + dd : sr_cyrl__translator.translate, + M : 'месец', + MM : sr_cyrl__translator.translate, + y : 'годину', + yy : sr_cyrl__translator.translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Serbian [sr] + //! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j + + var sr__translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jedne minute'], + mm: ['minut', 'minute', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mesec', 'meseca', 'meseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = sr__translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + sr__translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var sr = moment.defineLocale('sr', { + months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays: 'nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota'.split('_'), + weekdaysShort: 'ned._pon._uto._sre._čet._pet._sub.'.split('_'), + weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm', + LTS : 'H:mm:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm', + LLLL: 'dddd, D. MMMM YYYY H:mm' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sutra u] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedelju] [u] LT'; + case 3: + return '[u] [sredu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedelje] [u] LT', + '[prošlog] [ponedeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'pre %s', + s : 'nekoliko sekundi', + m : sr__translator.translate, + mm : sr__translator.translate, + h : sr__translator.translate, + hh : sr__translator.translate, + d : 'dan', + dd : sr__translator.translate, + M : 'mesec', + MM : sr__translator.translate, + y : 'godinu', + yy : sr__translator.translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Swazi [ss] + //! author : Nicolai Davies<mail@nicolai.io> : https://github.com/nicolaidavies + + + var ss = moment.defineLocale('ss', { + months : "Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split('_'), + monthsShort : 'Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo'.split('_'), + weekdays : 'Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo'.split('_'), + weekdaysShort : 'Lis_Umb_Lsb_Les_Lsi_Lsh_Umg'.split('_'), + weekdaysMin : 'Li_Us_Lb_Lt_Ls_Lh_Ug'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[Namuhla nga] LT', + nextDay : '[Kusasa nga] LT', + nextWeek : 'dddd [nga] LT', + lastDay : '[Itolo nga] LT', + lastWeek : 'dddd [leliphelile] [nga] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'nga %s', + past : 'wenteka nga %s', + s : 'emizuzwana lomcane', + m : 'umzuzu', + mm : '%d emizuzu', + h : 'lihora', + hh : '%d emahora', + d : 'lilanga', + dd : '%d emalanga', + M : 'inyanga', + MM : '%d tinyanga', + y : 'umnyaka', + yy : '%d iminyaka' + }, + meridiemParse: /ekuseni|emini|entsambama|ebusuku/, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'ekuseni'; + } else if (hours < 15) { + return 'emini'; + } else if (hours < 19) { + return 'entsambama'; + } else { + return 'ebusuku'; + } + }, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'ekuseni') { + return hour; + } else if (meridiem === 'emini') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'entsambama' || meridiem === 'ebusuku') { + if (hour === 0) { + return 0; + } + return hour + 12; + } + }, + ordinalParse: /\d{1,2}/, + ordinal : '%d', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Swedish [sv] + //! author : Jens Alm : https://github.com/ulmus + + var sv = moment.defineLocale('sv', { + months : 'januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december'.split('_'), + monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'), + weekdays : 'söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag'.split('_'), + weekdaysShort : 'sön_mån_tis_ons_tor_fre_lör'.split('_'), + weekdaysMin : 'sö_må_ti_on_to_fr_lö'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [kl.] HH:mm', + LLLL : 'dddd D MMMM YYYY [kl.] HH:mm', + lll : 'D MMM YYYY HH:mm', + llll : 'ddd D MMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Idag] LT', + nextDay: '[Imorgon] LT', + lastDay: '[Igår] LT', + nextWeek: '[På] dddd LT', + lastWeek: '[I] dddd[s] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : 'för %s sedan', + s : 'några sekunder', + m : 'en minut', + mm : '%d minuter', + h : 'en timme', + hh : '%d timmar', + d : 'en dag', + dd : '%d dagar', + M : 'en månad', + MM : '%d månader', + y : 'ett år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}(e|a)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'e' : + (b === 1) ? 'a' : + (b === 2) ? 'a' : + (b === 3) ? 'e' : 'e'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Swahili [sw] + //! author : Fahad Kassim : https://github.com/fadsel + + var sw = moment.defineLocale('sw', { + months : 'Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba'.split('_'), + monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi'.split('_'), + weekdaysShort : 'Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos'.split('_'), + weekdaysMin : 'J2_J3_J4_J5_Al_Ij_J1'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[leo saa] LT', + nextDay : '[kesho saa] LT', + nextWeek : '[wiki ijayo] dddd [saat] LT', + lastDay : '[jana] LT', + lastWeek : '[wiki iliyopita] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s baadaye', + past : 'tokea %s', + s : 'hivi punde', + m : 'dakika moja', + mm : 'dakika %d', + h : 'saa limoja', + hh : 'masaa %d', + d : 'siku moja', + dd : 'masiku %d', + M : 'mwezi mmoja', + MM : 'miezi %d', + y : 'mwaka mmoja', + yy : 'miaka %d' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Tamil [ta] + //! author : Arjunkumar Krishnamoorthy : https://github.com/tk120404 + + var ta__symbolMap = { + '1': '௧', + '2': '௨', + '3': '௩', + '4': '௪', + '5': '௫', + '6': '௬', + '7': '௭', + '8': '௮', + '9': '௯', + '0': '௦' + }, ta__numberMap = { + '௧': '1', + '௨': '2', + '௩': '3', + '௪': '4', + '௫': '5', + '௬': '6', + '௭': '7', + '௮': '8', + '௯': '9', + '௦': '0' + }; + + var ta = moment.defineLocale('ta', { + months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'), + weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'), + weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, HH:mm', + LLLL : 'dddd, D MMMM YYYY, HH:mm' + }, + calendar : { + sameDay : '[இன்று] LT', + nextDay : '[நாளை] LT', + nextWeek : 'dddd, LT', + lastDay : '[நேற்று] LT', + lastWeek : '[கடந்த வாரம்] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s இல்', + past : '%s முன்', + s : 'ஒரு சில விநாடிகள்', + m : 'ஒரு நிமிடம்', + mm : '%d நிமிடங்கள்', + h : 'ஒரு மணி நேரம்', + hh : '%d மணி நேரம்', + d : 'ஒரு நாள்', + dd : '%d நாட்கள்', + M : 'ஒரு மாதம்', + MM : '%d மாதங்கள்', + y : 'ஒரு வருடம்', + yy : '%d ஆண்டுகள்' + }, + ordinalParse: /\d{1,2}வது/, + ordinal : function (number) { + return number + 'வது'; + }, + preparse: function (string) { + return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) { + return ta__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return ta__symbolMap[match]; + }); + }, + // refer http://ta.wikipedia.org/s/1er1 + meridiemParse: /யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/, + meridiem : function (hour, minute, isLower) { + if (hour < 2) { + return ' யாமம்'; + } else if (hour < 6) { + return ' வைகறை'; // வைகறை + } else if (hour < 10) { + return ' காலை'; // காலை + } else if (hour < 14) { + return ' நண்பகல்'; // நண்பகல் + } else if (hour < 18) { + return ' எற்பாடு'; // எற்பாடு + } else if (hour < 22) { + return ' மாலை'; // மாலை + } else { + return ' யாமம்'; + } + }, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'யாமம்') { + return hour < 2 ? hour : hour + 12; + } else if (meridiem === 'வைகறை' || meridiem === 'காலை') { + return hour; + } else if (meridiem === 'நண்பகல்') { + return hour >= 10 ? hour : hour + 12; + } else { + return hour + 12; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Telugu [te] + //! author : Krishna Chaitanya Thota : https://github.com/kcthota + + var te = moment.defineLocale('te', { + months : 'జనవరి_ఫిబ్రవరి_మార్చి_ఏప్రిల్_మే_జూన్_జూలై_ఆగస్టు_సెప్టెంబర్_అక్టోబర్_నవంబర్_డిసెంబర్'.split('_'), + monthsShort : 'జన._ఫిబ్ర._మార్చి_ఏప్రి._మే_జూన్_జూలై_ఆగ._సెప్._అక్టో._నవ._డిసె.'.split('_'), + monthsParseExact : true, + weekdays : 'ఆదివారం_సోమవారం_మంగళవారం_బుధవారం_గురువారం_శుక్రవారం_శనివారం'.split('_'), + weekdaysShort : 'ఆది_సోమ_మంగళ_బుధ_గురు_శుక్ర_శని'.split('_'), + weekdaysMin : 'ఆ_సో_మం_బు_గు_శు_శ'.split('_'), + longDateFormat : { + LT : 'A h:mm', + LTS : 'A h:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm', + LLLL : 'dddd, D MMMM YYYY, A h:mm' + }, + calendar : { + sameDay : '[నేడు] LT', + nextDay : '[రేపు] LT', + nextWeek : 'dddd, LT', + lastDay : '[నిన్న] LT', + lastWeek : '[గత] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s లో', + past : '%s క్రితం', + s : 'కొన్ని క్షణాలు', + m : 'ఒక నిమిషం', + mm : '%d నిమిషాలు', + h : 'ఒక గంట', + hh : '%d గంటలు', + d : 'ఒక రోజు', + dd : '%d రోజులు', + M : 'ఒక నెల', + MM : '%d నెలలు', + y : 'ఒక సంవత్సరం', + yy : '%d సంవత్సరాలు' + }, + ordinalParse : /\d{1,2}వ/, + ordinal : '%dవ', + meridiemParse: /రాత్రి|ఉదయం|మధ్యాహ్నం|సాయంత్రం/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'రాత్రి') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'ఉదయం') { + return hour; + } else if (meridiem === 'మధ్యాహ్నం') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'సాయంత్రం') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'రాత్రి'; + } else if (hour < 10) { + return 'ఉదయం'; + } else if (hour < 17) { + return 'మధ్యాహ్నం'; + } else if (hour < 20) { + return 'సాయంత్రం'; + } else { + return 'రాత్రి'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Thai [th] + //! author : Kridsada Thanabulpong : https://github.com/sirn + + var th = moment.defineLocale('th', { + months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'), + monthsShort : 'ม.ค._ก.พ._มี.ค._เม.ย._พ.ค._มิ.ย._ก.ค._ส.ค._ก.ย._ต.ค._พ.ย._ธ.ค.'.split('_'), + monthsParseExact: true, + weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'), + weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference + weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H นาฬิกา m นาที', + LTS : 'H นาฬิกา m นาที s วินาที', + L : 'YYYY/MM/DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY เวลา H นาฬิกา m นาที', + LLLL : 'วันddddที่ D MMMM YYYY เวลา H นาฬิกา m นาที' + }, + meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/, + isPM: function (input) { + return input === 'หลังเที่ยง'; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ก่อนเที่ยง'; + } else { + return 'หลังเที่ยง'; + } + }, + calendar : { + sameDay : '[วันนี้ เวลา] LT', + nextDay : '[พรุ่งนี้ เวลา] LT', + nextWeek : 'dddd[หน้า เวลา] LT', + lastDay : '[เมื่อวานนี้ เวลา] LT', + lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'อีก %s', + past : '%sที่แล้ว', + s : 'ไม่กี่วินาที', + m : '1 นาที', + mm : '%d นาที', + h : '1 ชั่วโมง', + hh : '%d ชั่วโมง', + d : '1 วัน', + dd : '%d วัน', + M : '1 เดือน', + MM : '%d เดือน', + y : '1 ปี', + yy : '%d ปี' + } + }); + + //! moment.js locale configuration + //! locale : Tagalog (Philippines) [tl-ph] + //! author : Dan Hagman + + var tl_ph = moment.defineLocale('tl-ph', { + months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'), + monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'), + weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'), + weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'), + weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'MM/D/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY HH:mm', + LLLL : 'dddd, MMMM DD, YYYY HH:mm' + }, + calendar : { + sameDay: '[Ngayon sa] LT', + nextDay: '[Bukas sa] LT', + nextWeek: 'dddd [sa] LT', + lastDay: '[Kahapon sa] LT', + lastWeek: 'dddd [huling linggo] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'sa loob ng %s', + past : '%s ang nakalipas', + s : 'ilang segundo', + m : 'isang minuto', + mm : '%d minuto', + h : 'isang oras', + hh : '%d oras', + d : 'isang araw', + dd : '%d araw', + M : 'isang buwan', + MM : '%d buwan', + y : 'isang taon', + yy : '%d taon' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Klingon [tlh] + //! author : Dominika Kruk : https://github.com/amaranthrose + + var numbersNouns = 'pagh_wa’_cha’_wej_loS_vagh_jav_Soch_chorgh_Hut'.split('_'); + + function translateFuture(output) { + var time = output; + time = (output.indexOf('jaj') !== -1) ? + time.slice(0, -3) + 'leS' : + (output.indexOf('jar') !== -1) ? + time.slice(0, -3) + 'waQ' : + (output.indexOf('DIS') !== -1) ? + time.slice(0, -3) + 'nem' : + time + ' pIq'; + return time; + } + + function translatePast(output) { + var time = output; + time = (output.indexOf('jaj') !== -1) ? + time.slice(0, -3) + 'Hu’' : + (output.indexOf('jar') !== -1) ? + time.slice(0, -3) + 'wen' : + (output.indexOf('DIS') !== -1) ? + time.slice(0, -3) + 'ben' : + time + ' ret'; + return time; + } + + function tlh__translate(number, withoutSuffix, string, isFuture) { + var numberNoun = numberAsNoun(number); + switch (string) { + case 'mm': + return numberNoun + ' tup'; + case 'hh': + return numberNoun + ' rep'; + case 'dd': + return numberNoun + ' jaj'; + case 'MM': + return numberNoun + ' jar'; + case 'yy': + return numberNoun + ' DIS'; + } + } + + function numberAsNoun(number) { + var hundred = Math.floor((number % 1000) / 100), + ten = Math.floor((number % 100) / 10), + one = number % 10, + word = ''; + if (hundred > 0) { + word += numbersNouns[hundred] + 'vatlh'; + } + if (ten > 0) { + word += ((word !== '') ? ' ' : '') + numbersNouns[ten] + 'maH'; + } + if (one > 0) { + word += ((word !== '') ? ' ' : '') + numbersNouns[one]; + } + return (word === '') ? 'pagh' : word; + } + + var tlh = moment.defineLocale('tlh', { + months : 'tera’ jar wa’_tera’ jar cha’_tera’ jar wej_tera’ jar loS_tera’ jar vagh_tera’ jar jav_tera’ jar Soch_tera’ jar chorgh_tera’ jar Hut_tera’ jar wa’maH_tera’ jar wa’maH wa’_tera’ jar wa’maH cha’'.split('_'), + monthsShort : 'jar wa’_jar cha’_jar wej_jar loS_jar vagh_jar jav_jar Soch_jar chorgh_jar Hut_jar wa’maH_jar wa’maH wa’_jar wa’maH cha’'.split('_'), + monthsParseExact : true, + weekdays : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'), + weekdaysShort : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'), + weekdaysMin : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[DaHjaj] LT', + nextDay: '[wa’leS] LT', + nextWeek: 'LLL', + lastDay: '[wa’Hu’] LT', + lastWeek: 'LLL', + sameElse: 'L' + }, + relativeTime : { + future : translateFuture, + past : translatePast, + s : 'puS lup', + m : 'wa’ tup', + mm : tlh__translate, + h : 'wa’ rep', + hh : tlh__translate, + d : 'wa’ jaj', + dd : tlh__translate, + M : 'wa’ jar', + MM : tlh__translate, + y : 'wa’ DIS', + yy : tlh__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Turkish [tr] + //! authors : Erhan Gundogan : https://github.com/erhangundogan, + //! Burak Yiğit Kaya: https://github.com/BYK + + var tr__suffixes = { + 1: '\'inci', + 5: '\'inci', + 8: '\'inci', + 70: '\'inci', + 80: '\'inci', + 2: '\'nci', + 7: '\'nci', + 20: '\'nci', + 50: '\'nci', + 3: '\'üncü', + 4: '\'üncü', + 100: '\'üncü', + 6: '\'ncı', + 9: '\'uncu', + 10: '\'uncu', + 30: '\'uncu', + 60: '\'ıncı', + 90: '\'ıncı' + }; + + var tr = moment.defineLocale('tr', { + months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'), + monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'), + weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'), + weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'), + weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[bugün saat] LT', + nextDay : '[yarın saat] LT', + nextWeek : '[haftaya] dddd [saat] LT', + lastDay : '[dün] LT', + lastWeek : '[geçen hafta] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s sonra', + past : '%s önce', + s : 'birkaç saniye', + m : 'bir dakika', + mm : '%d dakika', + h : 'bir saat', + hh : '%d saat', + d : 'bir gün', + dd : '%d gün', + M : 'bir ay', + MM : '%d ay', + y : 'bir yıl', + yy : '%d yıl' + }, + ordinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/, + ordinal : function (number) { + if (number === 0) { // special case for zero + return number + '\'ıncı'; + } + var a = number % 10, + b = number % 100 - a, + c = number >= 100 ? 100 : null; + return number + (tr__suffixes[a] || tr__suffixes[b] || tr__suffixes[c]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Talossan [tzl] + //! author : Robin van der Vliet : https://github.com/robin0van0der0v with the help of Iustì Canun + + + // After the year there should be a slash and the amount of years since December 26, 1979 in Roman numerals. + // This is currently too difficult (maybe even impossible) to add. + var tzl = moment.defineLocale('tzl', { + months : 'Januar_Fevraglh_Març_Avrïu_Mai_Gün_Julia_Guscht_Setemvar_Listopäts_Noemvar_Zecemvar'.split('_'), + monthsShort : 'Jan_Fev_Mar_Avr_Mai_Gün_Jul_Gus_Set_Lis_Noe_Zec'.split('_'), + weekdays : 'Súladi_Lúneçi_Maitzi_Márcuri_Xhúadi_Viénerçi_Sáturi'.split('_'), + weekdaysShort : 'Súl_Lún_Mai_Már_Xhú_Vié_Sát'.split('_'), + weekdaysMin : 'Sú_Lú_Ma_Má_Xh_Vi_Sá'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM [dallas] YYYY', + LLL : 'D. MMMM [dallas] YYYY HH.mm', + LLLL : 'dddd, [li] D. MMMM [dallas] YYYY HH.mm' + }, + meridiemParse: /d\'o|d\'a/i, + isPM : function (input) { + return 'd\'o' === input.toLowerCase(); + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'd\'o' : 'D\'O'; + } else { + return isLower ? 'd\'a' : 'D\'A'; + } + }, + calendar : { + sameDay : '[oxhi à] LT', + nextDay : '[demà à] LT', + nextWeek : 'dddd [à] LT', + lastDay : '[ieiri à] LT', + lastWeek : '[sür el] dddd [lasteu à] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'osprei %s', + past : 'ja%s', + s : tzl__processRelativeTime, + m : tzl__processRelativeTime, + mm : tzl__processRelativeTime, + h : tzl__processRelativeTime, + hh : tzl__processRelativeTime, + d : tzl__processRelativeTime, + dd : tzl__processRelativeTime, + M : tzl__processRelativeTime, + MM : tzl__processRelativeTime, + y : tzl__processRelativeTime, + yy : tzl__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + function tzl__processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 's': ['viensas secunds', '\'iensas secunds'], + 'm': ['\'n míut', '\'iens míut'], + 'mm': [number + ' míuts', '' + number + ' míuts'], + 'h': ['\'n þora', '\'iensa þora'], + 'hh': [number + ' þoras', '' + number + ' þoras'], + 'd': ['\'n ziua', '\'iensa ziua'], + 'dd': [number + ' ziuas', '' + number + ' ziuas'], + 'M': ['\'n mes', '\'iens mes'], + 'MM': [number + ' mesen', '' + number + ' mesen'], + 'y': ['\'n ar', '\'iens ar'], + 'yy': [number + ' ars', '' + number + ' ars'] + }; + return isFuture ? format[key][0] : (withoutSuffix ? format[key][0] : format[key][1]); + } + + //! moment.js locale configuration + //! locale : Central Atlas Tamazight Latin [tzm-latn] + //! author : Abdel Said : https://github.com/abdelsaid + + var tzm_latn = moment.defineLocale('tzm-latn', { + months : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'), + monthsShort : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'), + weekdays : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), + weekdaysShort : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), + weekdaysMin : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[asdkh g] LT', + nextDay: '[aska g] LT', + nextWeek: 'dddd [g] LT', + lastDay: '[assant g] LT', + lastWeek: 'dddd [g] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dadkh s yan %s', + past : 'yan %s', + s : 'imik', + m : 'minuḍ', + mm : '%d minuḍ', + h : 'saɛa', + hh : '%d tassaɛin', + d : 'ass', + dd : '%d ossan', + M : 'ayowr', + MM : '%d iyyirn', + y : 'asgas', + yy : '%d isgasn' + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Central Atlas Tamazight [tzm] + //! author : Abdel Said : https://github.com/abdelsaid + + var tzm = moment.defineLocale('tzm', { + months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[ⴰⵙⴷⵅ ⴴ] LT', + nextDay: '[ⴰⵙⴽⴰ ⴴ] LT', + nextWeek: 'dddd [ⴴ] LT', + lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT', + lastWeek: 'dddd [ⴴ] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s', + past : 'ⵢⴰⵏ %s', + s : 'ⵉⵎⵉⴽ', + m : 'ⵎⵉⵏⵓⴺ', + mm : '%d ⵎⵉⵏⵓⴺ', + h : 'ⵙⴰⵄⴰ', + hh : '%d ⵜⴰⵙⵙⴰⵄⵉⵏ', + d : 'ⴰⵙⵙ', + dd : '%d oⵙⵙⴰⵏ', + M : 'ⴰⵢoⵓⵔ', + MM : '%d ⵉⵢⵢⵉⵔⵏ', + y : 'ⴰⵙⴳⴰⵙ', + yy : '%d ⵉⵙⴳⴰⵙⵏ' + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Ukrainian [uk] + //! author : zemlanin : https://github.com/zemlanin + //! Author : Menelion Elensúle : https://github.com/Oire + + function uk__plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); + } + function uk__relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'хвилина_хвилини_хвилин' : 'хвилину_хвилини_хвилин', + 'hh': withoutSuffix ? 'година_години_годин' : 'годину_години_годин', + 'dd': 'день_дні_днів', + 'MM': 'місяць_місяці_місяців', + 'yy': 'рік_роки_років' + }; + if (key === 'm') { + return withoutSuffix ? 'хвилина' : 'хвилину'; + } + else if (key === 'h') { + return withoutSuffix ? 'година' : 'годину'; + } + else { + return number + ' ' + uk__plural(format[key], +number); + } + } + function weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'), + 'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'), + 'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_') + }, + nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ? + 'accusative' : + ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ? + 'genitive' : + 'nominative'); + return weekdays[nounCase][m.day()]; + } + function processHoursFunction(str) { + return function () { + return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT'; + }; + } + + var uk = moment.defineLocale('uk', { + months : { + 'format': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_'), + 'standalone': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_') + }, + monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'), + weekdays : weekdaysCaseReplace, + weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY р.', + LLL : 'D MMMM YYYY р., HH:mm', + LLLL : 'dddd, D MMMM YYYY р., HH:mm' + }, + calendar : { + sameDay: processHoursFunction('[Сьогодні '), + nextDay: processHoursFunction('[Завтра '), + lastDay: processHoursFunction('[Вчора '), + nextWeek: processHoursFunction('[У] dddd ['), + lastWeek: function () { + switch (this.day()) { + case 0: + case 3: + case 5: + case 6: + return processHoursFunction('[Минулої] dddd [').call(this); + case 1: + case 2: + case 4: + return processHoursFunction('[Минулого] dddd [').call(this); + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'за %s', + past : '%s тому', + s : 'декілька секунд', + m : uk__relativeTimeWithPlural, + mm : uk__relativeTimeWithPlural, + h : 'годину', + hh : uk__relativeTimeWithPlural, + d : 'день', + dd : uk__relativeTimeWithPlural, + M : 'місяць', + MM : uk__relativeTimeWithPlural, + y : 'рік', + yy : uk__relativeTimeWithPlural + }, + // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason + meridiemParse: /ночі|ранку|дня|вечора/, + isPM: function (input) { + return /^(дня|вечора)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночі'; + } else if (hour < 12) { + return 'ранку'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечора'; + } + }, + ordinalParse: /\d{1,2}-(й|го)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + case 'w': + case 'W': + return number + '-й'; + case 'D': + return number + '-го'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Uzbek [uz] + //! author : Sardor Muminov : https://github.com/muminoff + + var uz = moment.defineLocale('uz', { + months : 'январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр'.split('_'), + monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'), + weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'), + weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'), + weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'D MMMM YYYY, dddd HH:mm' + }, + calendar : { + sameDay : '[Бугун соат] LT [да]', + nextDay : '[Эртага] LT [да]', + nextWeek : 'dddd [куни соат] LT [да]', + lastDay : '[Кеча соат] LT [да]', + lastWeek : '[Утган] dddd [куни соат] LT [да]', + sameElse : 'L' + }, + relativeTime : { + future : 'Якин %s ичида', + past : 'Бир неча %s олдин', + s : 'фурсат', + m : 'бир дакика', + mm : '%d дакика', + h : 'бир соат', + hh : '%d соат', + d : 'бир кун', + dd : '%d кун', + M : 'бир ой', + MM : '%d ой', + y : 'бир йил', + yy : '%d йил' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Vietnamese [vi] + //! author : Bang Nguyen : https://github.com/bangnk + + var vi = moment.defineLocale('vi', { + months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'), + monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'), + monthsParseExact : true, + weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'), + weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + weekdaysParseExact : true, + meridiemParse: /sa|ch/i, + isPM : function (input) { + return /^ch$/i.test(input); + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower ? 'sa' : 'SA'; + } else { + return isLower ? 'ch' : 'CH'; + } + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM [năm] YYYY', + LLL : 'D MMMM [năm] YYYY HH:mm', + LLLL : 'dddd, D MMMM [năm] YYYY HH:mm', + l : 'DD/M/YYYY', + ll : 'D MMM YYYY', + lll : 'D MMM YYYY HH:mm', + llll : 'ddd, D MMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Hôm nay lúc] LT', + nextDay: '[Ngày mai lúc] LT', + nextWeek: 'dddd [tuần tới lúc] LT', + lastDay: '[Hôm qua lúc] LT', + lastWeek: 'dddd [tuần rồi lúc] LT', + sameElse: 'L' + }, + relativeTime : { + future : '%s tới', + past : '%s trước', + s : 'vài giây', + m : 'một phút', + mm : '%d phút', + h : 'một giờ', + hh : '%d giờ', + d : 'một ngày', + dd : '%d ngày', + M : 'một tháng', + MM : '%d tháng', + y : 'một năm', + yy : '%d năm' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Pseudo [x-pseudo] + //! author : Andrew Hood : https://github.com/andrewhood125 + + var x_pseudo = moment.defineLocale('x-pseudo', { + months : 'J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér'.split('_'), + monthsShort : 'J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc'.split('_'), + monthsParseExact : true, + weekdays : 'S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý'.split('_'), + weekdaysShort : 'S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát'.split('_'), + weekdaysMin : 'S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[T~ódá~ý át] LT', + nextDay : '[T~ómó~rró~w át] LT', + nextWeek : 'dddd [át] LT', + lastDay : '[Ý~ést~érdá~ý át] LT', + lastWeek : '[L~ást] dddd [át] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'í~ñ %s', + past : '%s á~gó', + s : 'á ~féw ~sécó~ñds', + m : 'á ~míñ~úté', + mm : '%d m~íñú~tés', + h : 'á~ñ hó~úr', + hh : '%d h~óúrs', + d : 'á ~dáý', + dd : '%d d~áýs', + M : 'á ~móñ~th', + MM : '%d m~óñt~hs', + y : 'á ~ýéár', + yy : '%d ý~éárs' + }, + ordinalParse: /\d{1,2}(th|st|nd|rd)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Chinese (China) [zh-cn] + //! author : suupic : https://github.com/suupic + //! author : Zeno Zeng : https://github.com/zenozeng + + var zh_cn = moment.defineLocale('zh-cn', { + months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'), + monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'), + weekdaysShort : '周日_周一_周二_周三_周四_周五_周六'.split('_'), + weekdaysMin : '日_一_二_三_四_五_六'.split('_'), + longDateFormat : { + LT : 'Ah点mm分', + LTS : 'Ah点m分s秒', + L : 'YYYY-MM-DD', + LL : 'YYYY年MMMD日', + LLL : 'YYYY年MMMD日Ah点mm分', + LLLL : 'YYYY年MMMD日ddddAh点mm分', + l : 'YYYY-MM-DD', + ll : 'YYYY年MMMD日', + lll : 'YYYY年MMMD日Ah点mm分', + llll : 'YYYY年MMMD日ddddAh点mm分' + }, + meridiemParse: /凌晨|早上|上午|中午|下午|晚上/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '凌晨' || meridiem === '早上' || + meridiem === '上午') { + return hour; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } else { + // '中午' + return hour >= 11 ? hour : hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 600) { + return '凌晨'; + } else if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : function () { + return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT'; + }, + nextDay : function () { + return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT'; + }, + lastDay : function () { + return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT'; + }, + nextWeek : function () { + var startOfWeek, prefix; + startOfWeek = moment().startOf('week'); + prefix = this.diff(startOfWeek, 'days') >= 7 ? '[下]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + lastWeek : function () { + var startOfWeek, prefix; + startOfWeek = moment().startOf('week'); + prefix = this.unix() < startOfWeek.unix() ? '[上]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + sameElse : 'LL' + }, + ordinalParse: /\d{1,2}(日|月|周)/, + ordinal : function (number, period) { + switch (period) { + case 'd': + case 'D': + case 'DDD': + return number + '日'; + case 'M': + return number + '月'; + case 'w': + case 'W': + return number + '周'; + default: + return number; + } + }, + relativeTime : { + future : '%s内', + past : '%s前', + s : '几秒', + m : '1 分钟', + mm : '%d 分钟', + h : '1 小时', + hh : '%d 小时', + d : '1 天', + dd : '%d 天', + M : '1 个月', + MM : '%d 个月', + y : '1 年', + yy : '%d 年' + }, + week : { + // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效 + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : Chinese (Taiwan) [zh-tw] + //! author : Ben : https://github.com/ben-lin + //! author : Chris Lam : https://github.com/hehachris + + var zh_tw = moment.defineLocale('zh-tw', { + months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'), + monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'), + weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'), + weekdaysMin : '日_一_二_三_四_五_六'.split('_'), + longDateFormat : { + LT : 'Ah點mm分', + LTS : 'Ah點m分s秒', + L : 'YYYY年MMMD日', + LL : 'YYYY年MMMD日', + LLL : 'YYYY年MMMD日Ah點mm分', + LLLL : 'YYYY年MMMD日ddddAh點mm分', + l : 'YYYY年MMMD日', + ll : 'YYYY年MMMD日', + lll : 'YYYY年MMMD日Ah點mm分', + llll : 'YYYY年MMMD日ddddAh點mm分' + }, + meridiemParse: /凌晨|早上|上午|中午|下午|晚上/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') { + return hour; + } else if (meridiem === '中午') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 600) { + return '凌晨'; + } else if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : '[今天]LT', + nextDay : '[明天]LT', + nextWeek : '[下]ddddLT', + lastDay : '[昨天]LT', + lastWeek : '[上]ddddLT', + sameElse : 'L' + }, + ordinalParse: /\d{1,2}(日|月|週)/, + ordinal : function (number, period) { + switch (period) { + case 'd' : + case 'D' : + case 'DDD' : + return number + '日'; + case 'M' : + return number + '月'; + case 'w' : + case 'W' : + return number + '週'; + default : + return number; + } + }, + relativeTime : { + future : '%s內', + past : '%s前', + s : '幾秒', + m : '1 分鐘', + mm : '%d 分鐘', + h : '1 小時', + hh : '%d 小時', + d : '1 天', + dd : '%d 天', + M : '1 個月', + MM : '%d 個月', + y : '1 年', + yy : '%d 年' + } + }); + + moment.locale('en'); + +}));
@@ -0,0 +1,253 @@
+!function(a,b){"object"==typeof exports&&"undefined"!=typeof module&&"function"==typeof require?b(require("../moment")):"function"==typeof define&&define.amd?define(["../moment"],b):b(a.moment)}(this,function(a){"use strict"; +//! moment.js locale configuration +//! locale : Belarusian [be] +//! author : Dmitry Demidov : https://github.com/demidov91 +//! author: Praleska: http://praleska.pro/ +//! Author : Menelion Elensúle : https://github.com/Oire +function b(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function c(a,c,d){var e={mm:c?"хвіліна_хвіліны_хвілін":"хвіліну_хвіліны_хвілін",hh:c?"гадзіна_гадзіны_гадзін":"гадзіну_гадзіны_гадзін",dd:"дзень_дні_дзён",MM:"месяц_месяцы_месяцаў",yy:"год_гады_гадоў"};return"m"===d?c?"хвіліна":"хвіліну":"h"===d?c?"гадзіна":"гадзіну":a+" "+b(e[d],+a)} +//! moment.js locale configuration +//! locale : Breton [br] +//! author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou +function d(a,b,c){var d={mm:"munutenn",MM:"miz",dd:"devezh"};return a+" "+g(d[c],a)}function e(a){switch(f(a)){case 1:case 3:case 4:case 5:case 9:return a+" bloaz";default:return a+" vloaz"}}function f(a){return a>9?f(a%10):a}function g(a,b){return 2===b?h(a):a}function h(a){var b={m:"v",b:"v",d:"z"};return void 0===b[a.charAt(0)]?a:b[a.charAt(0)]+a.substring(1)} +//! moment.js locale configuration +//! locale : Bosnian [bs] +//! author : Nedim Cholich : https://github.com/frontyard +//! based on (hr) translation by Bojan Marković +function i(a,b,c){var d=a+" ";switch(c){case"m":return b?"jedna minuta":"jedne minute";case"mm":return d+=1===a?"minuta":2===a||3===a||4===a?"minute":"minuta";case"h":return b?"jedan sat":"jednog sata";case"hh":return d+=1===a?"sat":2===a||3===a||4===a?"sata":"sati";case"dd":return d+=1===a?"dan":"dana";case"MM":return d+=1===a?"mjesec":2===a||3===a||4===a?"mjeseca":"mjeseci";case"yy":return d+=1===a?"godina":2===a||3===a||4===a?"godine":"godina"}}function j(a){return a>1&&5>a&&1!==~~(a/10)}function k(a,b,c,d){var e=a+" ";switch(c){case"s":// a few seconds / in a few seconds / a few seconds ago +return b||d?"pár sekund":"pár sekundami";case"m":// a minute / in a minute / a minute ago +return b?"minuta":d?"minutu":"minutou";case"mm":// 9 minutes / in 9 minutes / 9 minutes ago +// 9 minutes / in 9 minutes / 9 minutes ago +return b||d?e+(j(a)?"minuty":"minut"):e+"minutami";break;case"h":// an hour / in an hour / an hour ago +return b?"hodina":d?"hodinu":"hodinou";case"hh":// 9 hours / in 9 hours / 9 hours ago +// 9 hours / in 9 hours / 9 hours ago +return b||d?e+(j(a)?"hodiny":"hodin"):e+"hodinami";break;case"d":// a day / in a day / a day ago +return b||d?"den":"dnem";case"dd":// 9 days / in 9 days / 9 days ago +// 9 days / in 9 days / 9 days ago +return b||d?e+(j(a)?"dny":"dní"):e+"dny";break;case"M":// a month / in a month / a month ago +return b||d?"měsíc":"měsícem";case"MM":// 9 months / in 9 months / 9 months ago +// 9 months / in 9 months / 9 months ago +return b||d?e+(j(a)?"měsíce":"měsíců"):e+"měsíci";break;case"y":// a year / in a year / a year ago +return b||d?"rok":"rokem";case"yy":// 9 years / in 9 years / 9 years ago +// 9 years / in 9 years / 9 years ago +return b||d?e+(j(a)?"roky":"let"):e+"lety"}} +//! moment.js locale configuration +//! locale : German (Austria) [de-at] +//! author : lluchs : https://github.com/lluchs +//! author: Menelion Elensúle: https://github.com/Oire +//! author : Martin Groller : https://github.com/MadMG +//! author : Mikolaj Dadela : https://github.com/mik01aj +function l(a,b,c,d){var e={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[a+" Tage",a+" Tagen"],M:["ein Monat","einem Monat"],MM:[a+" Monate",a+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[a+" Jahre",a+" Jahren"]};return b?e[c][0]:e[c][1]} +//! moment.js locale configuration +//! locale : German [de] +//! author : lluchs : https://github.com/lluchs +//! author: Menelion Elensúle: https://github.com/Oire +//! author : Mikolaj Dadela : https://github.com/mik01aj +function m(a,b,c,d){var e={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[a+" Tage",a+" Tagen"],M:["ein Monat","einem Monat"],MM:[a+" Monate",a+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[a+" Jahre",a+" Jahren"]};return b?e[c][0]:e[c][1]}function n(a){return a instanceof Function||"[object Function]"===Object.prototype.toString.call(a)} +//! moment.js locale configuration +//! locale : Estonian [et] +//! author : Henry Kehlmann : https://github.com/madhenry +//! improvements : Illimar Tambek : https://github.com/ragulka +function o(a,b,c,d){var e={s:["mõne sekundi","mõni sekund","paar sekundit"],m:["ühe minuti","üks minut"],mm:[a+" minuti",a+" minutit"],h:["ühe tunni","tund aega","üks tund"],hh:[a+" tunni",a+" tundi"],d:["ühe päeva","üks päev"],M:["kuu aja","kuu aega","üks kuu"],MM:[a+" kuu",a+" kuud"],y:["ühe aasta","aasta","üks aasta"],yy:[a+" aasta",a+" aastat"]};return b?e[c][2]?e[c][2]:e[c][1]:d?e[c][0]:e[c][1]}function p(a,b,c,d){var e="";switch(c){case"s":return d?"muutaman sekunnin":"muutama sekunti";case"m":return d?"minuutin":"minuutti";case"mm":e=d?"minuutin":"minuuttia";break;case"h":return d?"tunnin":"tunti";case"hh":e=d?"tunnin":"tuntia";break;case"d":return d?"päivän":"päivä";case"dd":e=d?"päivän":"päivää";break;case"M":return d?"kuukauden":"kuukausi";case"MM":e=d?"kuukauden":"kuukautta";break;case"y":return d?"vuoden":"vuosi";case"yy":e=d?"vuoden":"vuotta"}return e=q(a,d)+" "+e}function q(a,b){return 10>a?b?xa[a]:wa[a]:a} +//! moment.js locale configuration +//! locale : Croatian [hr] +//! author : Bojan Marković : https://github.com/bmarkovic +function r(a,b,c){var d=a+" ";switch(c){case"m":return b?"jedna minuta":"jedne minute";case"mm":return d+=1===a?"minuta":2===a||3===a||4===a?"minute":"minuta";case"h":return b?"jedan sat":"jednog sata";case"hh":return d+=1===a?"sat":2===a||3===a||4===a?"sata":"sati";case"dd":return d+=1===a?"dan":"dana";case"MM":return d+=1===a?"mjesec":2===a||3===a||4===a?"mjeseca":"mjeseci";case"yy":return d+=1===a?"godina":2===a||3===a||4===a?"godine":"godina"}}function s(a,b,c,d){var e=a;switch(c){case"s":return d||b?"néhány másodperc":"néhány másodperce";case"m":return"egy"+(d||b?" perc":" perce");case"mm":return e+(d||b?" perc":" perce");case"h":return"egy"+(d||b?" óra":" órája");case"hh":return e+(d||b?" óra":" órája");case"d":return"egy"+(d||b?" nap":" napja");case"dd":return e+(d||b?" nap":" napja");case"M":return"egy"+(d||b?" hónap":" hónapja");case"MM":return e+(d||b?" hónap":" hónapja");case"y":return"egy"+(d||b?" év":" éve");case"yy":return e+(d||b?" év":" éve")}return""}function t(a){return(a?"":"[múlt] ")+"["+Ha[this.day()]+"] LT[-kor]"} +//! moment.js locale configuration +//! locale : Icelandic [is] +//! author : Hinrik Örn Sigurðsson : https://github.com/hinrik +function u(a){return a%100===11?!0:a%10!==1}function v(a,b,c,d){var e=a+" ";switch(c){case"s":return b||d?"nokkrar sekúndur":"nokkrum sekúndum";case"m":return b?"mínúta":"mínútu";case"mm":return u(a)?e+(b||d?"mínútur":"mínútum"):b?e+"mínúta":e+"mínútu";case"hh":return u(a)?e+(b||d?"klukkustundir":"klukkustundum"):e+"klukkustund";case"d":return b?"dagur":d?"dag":"degi";case"dd":return u(a)?b?e+"dagar":e+(d?"daga":"dögum"):b?e+"dagur":e+(d?"dag":"degi");case"M":return b?"mánuður":d?"mánuð":"mánuði";case"MM":return u(a)?b?e+"mánuðir":e+(d?"mánuði":"mánuðum"):b?e+"mánuður":e+(d?"mánuð":"mánuði");case"y":return b||d?"ár":"ári";case"yy":return u(a)?e+(b||d?"ár":"árum"):e+(b||d?"ár":"ári")}} +//! moment.js locale configuration +//! locale : Luxembourgish [lb] +//! author : mweimerskirch : https://github.com/mweimerskirch, David Raison : https://github.com/kwisatz +function w(a,b,c,d){var e={m:["eng Minutt","enger Minutt"],h:["eng Stonn","enger Stonn"],d:["een Dag","engem Dag"],M:["ee Mount","engem Mount"],y:["ee Joer","engem Joer"]};return b?e[c][0]:e[c][1]}function x(a){var b=a.substr(0,a.indexOf(" "));return z(b)?"a "+a:"an "+a}function y(a){var b=a.substr(0,a.indexOf(" "));return z(b)?"viru "+a:"virun "+a}/** + * Returns true if the word before the given number loses the '-n' ending. + * e.g. 'an 10 Deeg' but 'a 5 Deeg' + * + * @param number {integer} + * @returns {boolean} + */ +function z(a){if(a=parseInt(a,10),isNaN(a))return!1;if(0>a) +// Negative Number --> always true +return!0;if(10>a) +// Only 1 digit +return a>=4&&7>=a;if(100>a){ +// 2 digits +var b=a%10,c=a/10;return z(0===b?c:b)}if(1e4>a){ +// 3 or 4 digits --> recursively check first digit +for(;a>=10;)a/=10;return z(a)} +// Anything larger than 4 digits: recursively check first n-3 digits +return a/=1e3,z(a)}function A(a,b,c,d){return b?"kelios sekundės":d?"kelių sekundžių":"kelias sekundes"}function B(a,b,c,d){return b?D(c)[0]:d?D(c)[1]:D(c)[2]}function C(a){return a%10===0||a>10&&20>a}function D(a){return Ka[a].split("_")}function E(a,b,c,d){var e=a+" ";return 1===a?e+B(a,b,c[0],d):b?e+(C(a)?D(c)[1]:D(c)[0]):d?e+D(c)[1]:e+(C(a)?D(c)[1]:D(c)[2])}/** + * @param withoutSuffix boolean true = a length of time; false = before/after a period of time. + */ +function F(a,b,c){return c?b%10===1&&b%100!==11?a[2]:a[3]:b%10===1&&b%100!==11?a[0]:a[1]}function G(a,b,c){return a+" "+F(La[c],a,b)}function H(a,b,c){return F(La[c],a,b)}function I(a,b){return b?"dažas sekundes":"dažām sekundēm"}function J(a,b,c,d){var e="";if(b)switch(c){case"s":e="काही सेकंद";break;case"m":e="एक मिनिट";break;case"mm":e="%d मिनिटे";break;case"h":e="एक तास";break;case"hh":e="%d तास";break;case"d":e="एक दिवस";break;case"dd":e="%d दिवस";break;case"M":e="एक महिना";break;case"MM":e="%d महिने";break;case"y":e="एक वर्ष";break;case"yy":e="%d वर्षे"}else switch(c){case"s":e="काही सेकंदां";break;case"m":e="एका मिनिटा";break;case"mm":e="%d मिनिटां";break;case"h":e="एका तासा";break;case"hh":e="%d तासां";break;case"d":e="एका दिवसा";break;case"dd":e="%d दिवसां";break;case"M":e="एका महिन्या";break;case"MM":e="%d महिन्यां";break;case"y":e="एका वर्षा";break;case"yy":e="%d वर्षां"}return e.replace(/%d/i,a)}function K(a){return 5>a%10&&a%10>1&&~~(a/10)%10!==1}function L(a,b,c){var d=a+" ";switch(c){case"m":return b?"minuta":"minutę";case"mm":return d+(K(a)?"minuty":"minut");case"h":return b?"godzina":"godzinę";case"hh":return d+(K(a)?"godziny":"godzin");case"MM":return d+(K(a)?"miesiące":"miesięcy");case"yy":return d+(K(a)?"lata":"lat")}} +//! moment.js locale configuration +//! locale : Romanian [ro] +//! author : Vlad Gurdiga : https://github.com/gurdiga +//! author : Valentin Agachi : https://github.com/avaly +function M(a,b,c){var d={mm:"minute",hh:"ore",dd:"zile",MM:"luni",yy:"ani"},e=" ";return(a%100>=20||a>=100&&a%100===0)&&(e=" de "),a+e+d[c]} +//! moment.js locale configuration +//! locale : Russian [ru] +//! author : Viktorminator : https://github.com/Viktorminator +//! Author : Menelion Elensúle : https://github.com/Oire +//! author : Коренберг Марк : https://github.com/socketpair +function N(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function O(a,b,c){var d={mm:b?"минута_минуты_минут":"минуту_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",MM:"месяц_месяца_месяцев",yy:"год_года_лет"};return"m"===c?b?"минута":"минуту":a+" "+N(d[c],+a)}function P(a){return a>1&&5>a}function Q(a,b,c,d){var e=a+" ";switch(c){case"s":// a few seconds / in a few seconds / a few seconds ago +return b||d?"pár sekúnd":"pár sekundami";case"m":// a minute / in a minute / a minute ago +return b?"minúta":d?"minútu":"minútou";case"mm":// 9 minutes / in 9 minutes / 9 minutes ago +// 9 minutes / in 9 minutes / 9 minutes ago +return b||d?e+(P(a)?"minúty":"minút"):e+"minútami";break;case"h":// an hour / in an hour / an hour ago +return b?"hodina":d?"hodinu":"hodinou";case"hh":// 9 hours / in 9 hours / 9 hours ago +// 9 hours / in 9 hours / 9 hours ago +return b||d?e+(P(a)?"hodiny":"hodín"):e+"hodinami";break;case"d":// a day / in a day / a day ago +return b||d?"deň":"dňom";case"dd":// 9 days / in 9 days / 9 days ago +// 9 days / in 9 days / 9 days ago +return b||d?e+(P(a)?"dni":"dní"):e+"dňami";break;case"M":// a month / in a month / a month ago +return b||d?"mesiac":"mesiacom";case"MM":// 9 months / in 9 months / 9 months ago +// 9 months / in 9 months / 9 months ago +return b||d?e+(P(a)?"mesiace":"mesiacov"):e+"mesiacmi";break;case"y":// a year / in a year / a year ago +return b||d?"rok":"rokom";case"yy":// 9 years / in 9 years / 9 years ago +// 9 years / in 9 years / 9 years ago +return b||d?e+(P(a)?"roky":"rokov"):e+"rokmi"}} +//! moment.js locale configuration +//! locale : Slovenian [sl] +//! author : Robert Sedovšek : https://github.com/sedovsek +function R(a,b,c,d){var e=a+" ";switch(c){case"s":return b||d?"nekaj sekund":"nekaj sekundami";case"m":return b?"ena minuta":"eno minuto";case"mm":return e+=1===a?b?"minuta":"minuto":2===a?b||d?"minuti":"minutama":5>a?b||d?"minute":"minutami":b||d?"minut":"minutami";case"h":return b?"ena ura":"eno uro";case"hh":return e+=1===a?b?"ura":"uro":2===a?b||d?"uri":"urama":5>a?b||d?"ure":"urami":b||d?"ur":"urami";case"d":return b||d?"en dan":"enim dnem";case"dd":return e+=1===a?b||d?"dan":"dnem":2===a?b||d?"dni":"dnevoma":b||d?"dni":"dnevi";case"M":return b||d?"en mesec":"enim mesecem";case"MM":return e+=1===a?b||d?"mesec":"mesecem":2===a?b||d?"meseca":"mesecema":5>a?b||d?"mesece":"meseci":b||d?"mesecev":"meseci";case"y":return b||d?"eno leto":"enim letom";case"yy":return e+=1===a?b||d?"leto":"letom":2===a?b||d?"leti":"letoma":5>a?b||d?"leta":"leti":b||d?"let":"leti"}}function S(a){var b=a;return b=-1!==a.indexOf("jaj")?b.slice(0,-3)+"leS":-1!==a.indexOf("jar")?b.slice(0,-3)+"waQ":-1!==a.indexOf("DIS")?b.slice(0,-3)+"nem":b+" pIq"}function T(a){var b=a;return b=-1!==a.indexOf("jaj")?b.slice(0,-3)+"Hu’":-1!==a.indexOf("jar")?b.slice(0,-3)+"wen":-1!==a.indexOf("DIS")?b.slice(0,-3)+"ben":b+" ret"}function U(a,b,c,d){var e=V(a);switch(c){case"mm":return e+" tup";case"hh":return e+" rep";case"dd":return e+" jaj";case"MM":return e+" jar";case"yy":return e+" DIS"}}function V(a){var b=Math.floor(a%1e3/100),c=Math.floor(a%100/10),d=a%10,e="";return b>0&&(e+=eb[b]+"vatlh"),c>0&&(e+=(""!==e?" ":"")+eb[c]+"maH"),d>0&&(e+=(""!==e?" ":"")+eb[d]),""===e?"pagh":e}function W(a,b,c,d){var e={s:["viensas secunds","'iensas secunds"],m:["'n míut","'iens míut"],mm:[a+" míuts",""+a+" míuts"],h:["'n þora","'iensa þora"],hh:[a+" þoras",""+a+" þoras"],d:["'n ziua","'iensa ziua"],dd:[a+" ziuas",""+a+" ziuas"],M:["'n mes","'iens mes"],MM:[a+" mesen",""+a+" mesen"],y:["'n ar","'iens ar"],yy:[a+" ars",""+a+" ars"]};return d?e[c][0]:b?e[c][0]:e[c][1]} +//! moment.js locale configuration +//! locale : Ukrainian [uk] +//! author : zemlanin : https://github.com/zemlanin +//! Author : Menelion Elensúle : https://github.com/Oire +function X(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function Y(a,b,c){var d={mm:b?"хвилина_хвилини_хвилин":"хвилину_хвилини_хвилин",hh:b?"година_години_годин":"годину_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"};return"m"===c?b?"хвилина":"хвилину":"h"===c?b?"година":"годину":a+" "+X(d[c],+a)}function Z(a,b){var c={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".split("_"),accusative:"неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу".split("_"),genitive:"неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи".split("_")},d=/(\[[ВвУу]\]) ?dddd/.test(b)?"accusative":/\[?(?:минулої|наступної)? ?\] ?dddd/.test(b)?"genitive":"nominative";return c[d][a.day()]}function $(a){return function(){return a+"о"+(11===this.hours()?"б":"")+"] LT"}} +//! moment.js locale configuration +//! locale : Afrikaans [af] +//! author : Werner Mollentze : https://github.com/wernerm +var _=(a.defineLocale("af",{months:"Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des".split("_"),weekdays:"Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag".split("_"),weekdaysShort:"Son_Maa_Din_Woe_Don_Vry_Sat".split("_"),weekdaysMin:"So_Ma_Di_Wo_Do_Vr_Sa".split("_"),meridiemParse:/vm|nm/i,isPM:function(a){return/^nm$/i.test(a)},meridiem:function(a,b,c){return 12>a?c?"vm":"VM":c?"nm":"NM"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Vandag om] LT",nextDay:"[Môre om] LT",nextWeek:"dddd [om] LT",lastDay:"[Gister om] LT",lastWeek:"[Laas] dddd [om] LT",sameElse:"L"},relativeTime:{future:"oor %s",past:"%s gelede",s:"'n paar sekondes",m:"'n minuut",mm:"%d minute",h:"'n uur",hh:"%d ure",d:"'n dag",dd:"%d dae",M:"'n maand",MM:"%d maande",y:"'n jaar",yy:"%d jaar"},ordinalParse:/\d{1,2}(ste|de)/,ordinal:function(a){return a+(1===a||8===a||a>=20?"ste":"de")},week:{dow:1,// Maandag is die eerste dag van die week. +doy:4}}),a.defineLocale("ar-ma",{months:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),weekdays:"الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:6,// Saturday is the first day of the week. +doy:12}}),{1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"}),aa={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"},ba=(a.defineLocale("ar-sa",{months:"يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(a){return"م"===a},meridiem:function(a,b,c){return 12>a?"ص":"م"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},preparse:function(a){return a.replace(/[١٢٣٤٥٦٧٨٩٠]/g,function(a){return aa[a]}).replace(/،/g,",")},postformat:function(a){return a.replace(/\d/g,function(a){return _[a]}).replace(/,/g,"،")},week:{dow:6,// Saturday is the first day of the week. +doy:12}}),a.defineLocale("ar-tn",{months:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:1,// Monday is the first day of the week. +doy:4}}),{1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"}),ca={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"},da=function(a){return 0===a?0:1===a?1:2===a?2:a%100>=3&&10>=a%100?3:a%100>=11?4:5},ea={s:["أقل من ثانية","ثانية واحدة",["ثانيتان","ثانيتين"],"%d ثوان","%d ثانية","%d ثانية"],m:["أقل من دقيقة","دقيقة واحدة",["دقيقتان","دقيقتين"],"%d دقائق","%d دقيقة","%d دقيقة"],h:["أقل من ساعة","ساعة واحدة",["ساعتان","ساعتين"],"%d ساعات","%d ساعة","%d ساعة"],d:["أقل من يوم","يوم واحد",["يومان","يومين"],"%d أيام","%d يومًا","%d يوم"],M:["أقل من شهر","شهر واحد",["شهران","شهرين"],"%d أشهر","%d شهرا","%d شهر"],y:["أقل من عام","عام واحد",["عامان","عامين"],"%d أعوام","%d عامًا","%d عام"]},fa=function(a){return function(b,c,d,e){var f=da(b),g=ea[a][da(b)];return 2===f&&(g=g[c?0:1]),g.replace(/%d/i,b)}},ga=["كانون الثاني يناير","شباط فبراير","آذار مارس","نيسان أبريل","أيار مايو","حزيران يونيو","تموز يوليو","آب أغسطس","أيلول سبتمبر","تشرين الأول أكتوبر","تشرين الثاني نوفمبر","كانون الأول ديسمبر"],ha=(a.defineLocale("ar",{months:ga,monthsShort:ga,weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/M/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(a){return"م"===a},meridiem:function(a,b,c){return 12>a?"ص":"م"},calendar:{sameDay:"[اليوم عند الساعة] LT",nextDay:"[غدًا عند الساعة] LT",nextWeek:"dddd [عند الساعة] LT",lastDay:"[أمس عند الساعة] LT",lastWeek:"dddd [عند الساعة] LT",sameElse:"L"},relativeTime:{future:"بعد %s",past:"منذ %s",s:fa("s"),m:fa("m"),mm:fa("m"),h:fa("h"),hh:fa("h"),d:fa("d"),dd:fa("d"),M:fa("M"),MM:fa("M"),y:fa("y"),yy:fa("y")},preparse:function(a){return a.replace(/\u200f/g,"").replace(/[١٢٣٤٥٦٧٨٩٠]/g,function(a){return ca[a]}).replace(/،/g,",")},postformat:function(a){return a.replace(/\d/g,function(a){return ba[a]}).replace(/,/g,"،")},week:{dow:6,// Saturday is the first day of the week. +doy:12}}),{1:"-inci",5:"-inci",8:"-inci",70:"-inci",80:"-inci",2:"-nci",7:"-nci",20:"-nci",50:"-nci",3:"-üncü",4:"-üncü",100:"-üncü",6:"-ncı",9:"-uncu",10:"-uncu",30:"-uncu",60:"-ıncı",90:"-ıncı"}),ia=(a.defineLocale("az",{months:"yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr".split("_"),monthsShort:"yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek".split("_"),weekdays:"Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə".split("_"),weekdaysShort:"Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən".split("_"),weekdaysMin:"Bz_BE_ÇA_Çə_CA_Cü_Şə".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[sabah saat] LT",nextWeek:"[gələn həftə] dddd [saat] LT",lastDay:"[dünən] LT",lastWeek:"[keçən həftə] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s əvvəl",s:"birneçə saniyyə",m:"bir dəqiqə",mm:"%d dəqiqə",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir il",yy:"%d il"},meridiemParse:/gecə|səhər|gündüz|axşam/,isPM:function(a){return/^(gündüz|axşam)$/.test(a)},meridiem:function(a,b,c){return 4>a?"gecə":12>a?"səhər":17>a?"gündüz":"axşam"},ordinalParse:/\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,ordinal:function(a){if(0===a)// special case for zero +return a+"-ıncı";var b=a%10,c=a%100-b,d=a>=100?100:null;return a+(ha[b]||ha[c]||ha[d])},week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("be",{months:{format:"студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня".split("_"),standalone:"студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань".split("_")},monthsShort:"студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж".split("_"),weekdays:{format:"нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу".split("_"),standalone:"нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота".split("_"),isFormat:/\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/},weekdaysShort:"нд_пн_ат_ср_чц_пт_сб".split("_"),weekdaysMin:"нд_пн_ат_ср_чц_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., HH:mm",LLLL:"dddd, D MMMM YYYY г., HH:mm"},calendar:{sameDay:"[Сёння ў] LT",nextDay:"[Заўтра ў] LT",lastDay:"[Учора ў] LT",nextWeek:function(){return"[У] dddd [ў] LT"},lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return"[У мінулую] dddd [ў] LT";case 1:case 2:case 4:return"[У мінулы] dddd [ў] LT"}},sameElse:"L"},relativeTime:{future:"праз %s",past:"%s таму",s:"некалькі секунд",m:c,mm:c,h:c,hh:c,d:"дзень",dd:c,M:"месяц",MM:c,y:"год",yy:c},meridiemParse:/ночы|раніцы|дня|вечара/,isPM:function(a){return/^(дня|вечара)$/.test(a)},meridiem:function(a,b,c){return 4>a?"ночы":12>a?"раніцы":17>a?"дня":"вечара"},ordinalParse:/\d{1,2}-(і|ы|га)/,ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":case"w":case"W":return a%10!==2&&a%10!==3||a%100===12||a%100===13?a+"-ы":a+"-і";case"D":return a+"-га";default:return a}},week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("bg",{months:"януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),monthsShort:"янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"),weekdays:"неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"),weekdaysShort:"нед_пон_вто_сря_чет_пет_съб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[Днес в] LT",nextDay:"[Утре в] LT",nextWeek:"dddd [в] LT",lastDay:"[Вчера в] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[В изминалата] dddd [в] LT";case 1:case 2:case 4:case 5:return"[В изминалия] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"след %s",past:"преди %s",s:"няколко секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дни",M:"месец",MM:"%d месеца",y:"година",yy:"%d години"},ordinalParse:/\d{1,2}-(ев|ен|ти|ви|ри|ми)/,ordinal:function(a){var b=a%10,c=a%100;return 0===a?a+"-ев":0===c?a+"-ен":c>10&&20>c?a+"-ти":1===b?a+"-ви":2===b?a+"-ри":7===b||8===b?a+"-ми":a+"-ти"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),{1:"১",2:"২",3:"৩",4:"৪",5:"৫",6:"৬",7:"৭",8:"৮",9:"৯",0:"০"}),ja={"১":"1","২":"2","৩":"3","৪":"4","৫":"5","৬":"6","৭":"7","৮":"8","৯":"9","০":"0"},ka=(a.defineLocale("bn",{months:"জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর".split("_"),monthsShort:"জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্".split("_"),weekdays:"রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রবার_শনিবার".split("_"),weekdaysShort:"রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্র_শনি".split("_"),weekdaysMin:"রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি".split("_"),longDateFormat:{LT:"A h:mm সময়",LTS:"A h:mm:ss সময়",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm সময়",LLLL:"dddd, D MMMM YYYY, A h:mm সময়"},calendar:{sameDay:"[আজ] LT",nextDay:"[আগামীকাল] LT",nextWeek:"dddd, LT",lastDay:"[গতকাল] LT",lastWeek:"[গত] dddd, LT",sameElse:"L"},relativeTime:{future:"%s পরে",past:"%s আগে",s:"কয়েক সেকেন্ড",m:"এক মিনিট",mm:"%d মিনিট",h:"এক ঘন্টা",hh:"%d ঘন্টা",d:"এক দিন",dd:"%d দিন",M:"এক মাস",MM:"%d মাস",y:"এক বছর",yy:"%d বছর"},preparse:function(a){return a.replace(/[১২৩৪৫৬৭৮৯০]/g,function(a){return ja[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return ia[a]})},meridiemParse:/রাত|সকাল|দুপুর|বিকাল|রাত/,meridiemHour:function(a,b){return 12===a&&(a=0),"রাত"===b&&a>=4||"দুপুর"===b&&5>a||"বিকাল"===b?a+12:a},meridiem:function(a,b,c){return 4>a?"রাত":10>a?"সকাল":17>a?"দুপুর":20>a?"বিকাল":"রাত"},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),{1:"༡",2:"༢",3:"༣",4:"༤",5:"༥",6:"༦",7:"༧",8:"༨",9:"༩",0:"༠"}),la={"༡":"1","༢":"2","༣":"3","༤":"4","༥":"5","༦":"6","༧":"7","༨":"8","༩":"9","༠":"0"},ma=(a.defineLocale("bo",{months:"ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ".split("_"),monthsShort:"ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ".split("_"),weekdays:"གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་".split("_"),weekdaysShort:"ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་".split("_"),weekdaysMin:"ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[དི་རིང] LT",nextDay:"[སང་ཉིན] LT",nextWeek:"[བདུན་ཕྲག་རྗེས་མ], LT",lastDay:"[ཁ་སང] LT",lastWeek:"[བདུན་ཕྲག་མཐའ་མ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s ལ་",past:"%s སྔན་ལ",s:"ལམ་སང",m:"སྐར་མ་གཅིག",mm:"%d སྐར་མ",h:"ཆུ་ཚོད་གཅིག",hh:"%d ཆུ་ཚོད",d:"ཉིན་གཅིག",dd:"%d ཉིན་",M:"ཟླ་བ་གཅིག",MM:"%d ཟླ་བ",y:"ལོ་གཅིག",yy:"%d ལོ"},preparse:function(a){return a.replace(/[༡༢༣༤༥༦༧༨༩༠]/g,function(a){return la[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return ka[a]})},meridiemParse:/མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/,meridiemHour:function(a,b){return 12===a&&(a=0),"མཚན་མོ"===b&&a>=4||"ཉིན་གུང"===b&&5>a||"དགོང་དག"===b?a+12:a},meridiem:function(a,b,c){return 4>a?"མཚན་མོ":10>a?"ཞོགས་ཀས":17>a?"ཉིན་གུང":20>a?"དགོང་དག":"མཚན་མོ"},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),a.defineLocale("br",{months:"Genver_C'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"),monthsShort:"Gen_C'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"),weekdays:"Sul_Lun_Meurzh_Merc'her_Yaou_Gwener_Sadorn".split("_"),weekdaysShort:"Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"),weekdaysMin:"Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h[e]mm A",LTS:"h[e]mm:ss A",L:"DD/MM/YYYY",LL:"D [a viz] MMMM YYYY",LLL:"D [a viz] MMMM YYYY h[e]mm A",LLLL:"dddd, D [a viz] MMMM YYYY h[e]mm A"},calendar:{sameDay:"[Hiziv da] LT",nextDay:"[Warc'hoazh da] LT",nextWeek:"dddd [da] LT",lastDay:"[Dec'h da] LT",lastWeek:"dddd [paset da] LT",sameElse:"L"},relativeTime:{future:"a-benn %s",past:"%s 'zo",s:"un nebeud segondennoù",m:"ur vunutenn",mm:d,h:"un eur",hh:"%d eur",d:"un devezh",dd:d,M:"ur miz",MM:d,y:"ur bloaz",yy:e},ordinalParse:/\d{1,2}(añ|vet)/,ordinal:function(a){var b=1===a?"añ":"vet";return a+b},week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("bs",{months:"januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",m:i,mm:i,h:i,hh:i,d:"dan",dd:i,M:"mjesec",MM:i,y:"godinu",yy:i},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("ca",{months:"gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre".split("_"),monthsShort:"gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.".split("_"),monthsParseExact:!0,weekdays:"diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte".split("_"),weekdaysShort:"dg._dl._dt._dc._dj._dv._ds.".split("_"),weekdaysMin:"Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd D MMMM YYYY H:mm"},calendar:{sameDay:function(){return"[avui a "+(1!==this.hours()?"les":"la")+"] LT"},nextDay:function(){return"[demà a "+(1!==this.hours()?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(1!==this.hours()?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(1!==this.hours()?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(1!==this.hours()?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fa %s",s:"uns segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},ordinalParse:/\d{1,2}(r|n|t|è|a)/,ordinal:function(a,b){var c=1===a?"r":2===a?"n":3===a?"r":4===a?"t":"è";return"w"!==b&&"W"!==b||(c="a"),a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),"leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_")),na="led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_"),oa=(a.defineLocale("cs",{months:ma,monthsShort:na,monthsParse:function(a,b){var c,d=[];for(c=0;12>c;c++) +// use custom parser to solve problem with July (červenec) +d[c]=new RegExp("^"+a[c]+"$|^"+b[c]+"$","i");return d}(ma,na),shortMonthsParse:function(a){var b,c=[];for(b=0;12>b;b++)c[b]=new RegExp("^"+a[b]+"$","i");return c}(na),longMonthsParse:function(a){var b,c=[];for(b=0;12>b;b++)c[b]=new RegExp("^"+a[b]+"$","i");return c}(ma),weekdays:"neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"),weekdaysShort:"ne_po_út_st_čt_pá_so".split("_"),weekdaysMin:"ne_po_út_st_čt_pá_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm",l:"D. M. YYYY"},calendar:{sameDay:"[dnes v] LT",nextDay:"[zítra v] LT",nextWeek:function(){switch(this.day()){case 0:return"[v neděli v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve středu v] LT";case 4:return"[ve čtvrtek v] LT";case 5:return"[v pátek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[včera v] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulou neděli v] LT";case 1:case 2:return"[minulé] dddd [v] LT";case 3:return"[minulou středu v] LT";case 4:case 5:return"[minulý] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"před %s",s:k,m:k,mm:k,h:k,hh:k,d:k,dd:k,M:k,MM:k,y:k,yy:k},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("cv",{months:"кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав".split("_"),monthsShort:"кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш".split("_"),weekdays:"вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун".split("_"),weekdaysShort:"выр_тун_ытл_юн_кӗҫ_эрн_шӑм".split("_"),weekdaysMin:"вр_тн_ыт_юн_кҫ_эр_шм".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]",LLL:"YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm",LLLL:"dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm"},calendar:{sameDay:"[Паян] LT [сехетре]",nextDay:"[Ыран] LT [сехетре]",lastDay:"[Ӗнер] LT [сехетре]",nextWeek:"[Ҫитес] dddd LT [сехетре]",lastWeek:"[Иртнӗ] dddd LT [сехетре]",sameElse:"L"},relativeTime:{future:function(a){var b=/сехет$/i.exec(a)?"рен":/ҫул$/i.exec(a)?"тан":"ран";return a+b},past:"%s каялла",s:"пӗр-ик ҫеккунт",m:"пӗр минут",mm:"%d минут",h:"пӗр сехет",hh:"%d сехет",d:"пӗр кун",dd:"%d кун",M:"пӗр уйӑх",MM:"%d уйӑх",y:"пӗр ҫул",yy:"%d ҫул"},ordinalParse:/\d{1,2}-мӗш/,ordinal:"%d-мӗш",week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("cy",{months:"Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr".split("_"),monthsShort:"Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag".split("_"),weekdays:"Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn".split("_"),weekdaysShort:"Sul_Llun_Maw_Mer_Iau_Gwe_Sad".split("_"),weekdaysMin:"Su_Ll_Ma_Me_Ia_Gw_Sa".split("_"),weekdaysParseExact:!0, +// time formats are the same as en-gb +longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Heddiw am] LT",nextDay:"[Yfory am] LT",nextWeek:"dddd [am] LT",lastDay:"[Ddoe am] LT",lastWeek:"dddd [diwethaf am] LT",sameElse:"L"},relativeTime:{future:"mewn %s",past:"%s yn ôl",s:"ychydig eiliadau",m:"munud",mm:"%d munud",h:"awr",hh:"%d awr",d:"diwrnod",dd:"%d diwrnod",M:"mis",MM:"%d mis",y:"blwyddyn",yy:"%d flynedd"},ordinalParse:/\d{1,2}(fed|ain|af|il|ydd|ed|eg)/, +// traditional ordinal numbers above 31 are not commonly used in colloquial Welsh +ordinal:function(a){var b=a,c="",d=["","af","il","ydd","ydd","ed","ed","ed","fed","fed","fed",// 1af to 10fed +"eg","fed","eg","eg","fed","eg","eg","fed","eg","fed"];return b>20?c=40===b||50===b||60===b||80===b||100===b?"fed":"ain":b>0&&(c=d[b]),a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("da",{months:"januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd [d.] D. MMMM YYYY HH:mm"},calendar:{sameDay:"[I dag kl.] LT",nextDay:"[I morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[I går kl.] LT",lastWeek:"[sidste] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"få sekunder",m:"et minut",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dage",M:"en måned",MM:"%d måneder",y:"et år",yy:"%d år"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("de-at",{months:"Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:l,mm:"%d Minuten",h:l,hh:"%d Stunden",d:l,dd:l,M:l,MM:l,y:l,yy:l},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:m,mm:"%d Minuten",h:m,hh:"%d Stunden",d:m,dd:m,M:m,MM:m,y:m,yy:m},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),["ޖެނުއަރީ","ފެބްރުއަރީ","މާރިޗު","އޭޕްރީލު","މޭ","ޖޫން","ޖުލައި","އޯގަސްޓު","ސެޕްޓެމްބަރު","އޮކްޓޯބަރު","ނޮވެމްބަރު","ޑިސެމްބަރު"]),pa=["އާދިއްތަ","ހޯމަ","އަންގާރަ","ބުދަ","ބުރާސްފަތި","ހުކުރު","ހޮނިހިރު"],qa=(a.defineLocale("dv",{months:oa,monthsShort:oa,weekdays:pa,weekdaysShort:pa,weekdaysMin:"އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/M/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/މކ|މފ/,isPM:function(a){return"މފ"===a},meridiem:function(a,b,c){return 12>a?"މކ":"މފ"},calendar:{sameDay:"[މިއަދު] LT",nextDay:"[މާދަމާ] LT",nextWeek:"dddd LT",lastDay:"[އިއްޔެ] LT",lastWeek:"[ފާއިތުވި] dddd LT",sameElse:"L"},relativeTime:{future:"ތެރޭގައި %s",past:"ކުރިން %s",s:"ސިކުންތުކޮޅެއް",m:"މިނިޓެއް",mm:"މިނިޓު %d",h:"ގަޑިއިރެއް",hh:"ގަޑިއިރު %d",d:"ދުވަހެއް",dd:"ދުވަސް %d",M:"މަހެއް",MM:"މަސް %d",y:"އަހަރެއް",yy:"އަހަރު %d"},preparse:function(a){return a.replace(/،/g,",")},postformat:function(a){return a.replace(/,/g,"،")},week:{dow:7,// Sunday is the first day of the week. +doy:12}}),a.defineLocale("el",{monthsNominativeEl:"Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"),monthsGenitiveEl:"Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"),months:function(a,b){return/D/.test(b.substring(0,b.indexOf("MMMM")))?this._monthsGenitiveEl[a.month()]:this._monthsNominativeEl[a.month()]},monthsShort:"Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"),weekdays:"Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"),weekdaysShort:"Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"),weekdaysMin:"Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"),meridiem:function(a,b,c){return a>11?c?"μμ":"ΜΜ":c?"πμ":"ΠΜ"},isPM:function(a){return"μ"===(a+"").toLowerCase()[0]},meridiemParse:/[ΠΜ]\.?Μ?\.?/i,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendarEl:{sameDay:"[Σήμερα {}] LT",nextDay:"[Αύριο {}] LT",nextWeek:"dddd [{}] LT",lastDay:"[Χθες {}] LT",lastWeek:function(){switch(this.day()){case 6:return"[το προηγούμενο] dddd [{}] LT";default:return"[την προηγούμενη] dddd [{}] LT"}},sameElse:"L"},calendar:function(a,b){var c=this._calendarEl[a],d=b&&b.hours();return n(c)&&(c=c.apply(b)),c.replace("{}",d%12===1?"στη":"στις")},relativeTime:{future:"σε %s",past:"%s πριν",s:"λίγα δευτερόλεπτα",m:"ένα λεπτό",mm:"%d λεπτά",h:"μία ώρα",hh:"%d ώρες",d:"μία μέρα",dd:"%d μέρες",M:"ένας μήνας",MM:"%d μήνες",y:"ένας χρόνος",yy:"%d χρόνια"},ordinalParse:/\d{1,2}η/,ordinal:"%dη",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("en-au",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("en-ca",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"YYYY-MM-DD",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.defineLocale("en-gb",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("en-ie",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("en-nz",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("eo",{months:"januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec".split("_"),weekdays:"Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato".split("_"),weekdaysShort:"Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Ĵa_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D[-an de] MMMM, YYYY",LLL:"D[-an de] MMMM, YYYY HH:mm",LLLL:"dddd, [la] D[-an de] MMMM, YYYY HH:mm"},meridiemParse:/[ap]\.t\.m/i,isPM:function(a){return"p"===a.charAt(0).toLowerCase()},meridiem:function(a,b,c){return a>11?c?"p.t.m.":"P.T.M.":c?"a.t.m.":"A.T.M."},calendar:{sameDay:"[Hodiaŭ je] LT",nextDay:"[Morgaŭ je] LT",nextWeek:"dddd [je] LT",lastDay:"[Hieraŭ je] LT",lastWeek:"[pasinta] dddd [je] LT",sameElse:"L"},relativeTime:{future:"je %s",past:"antaŭ %s",s:"sekundoj",m:"minuto",mm:"%d minutoj",h:"horo",hh:"%d horoj",d:"tago",//ne 'diurno', ĉar estas uzita por proksimumo +dd:"%d tagoj",M:"monato",MM:"%d monatoj",y:"jaro",yy:"%d jaroj"},ordinalParse:/\d{1,2}a/,ordinal:"%da",week:{dow:1,// Monday is the first day of the week. +doy:7}}),"ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_")),ra="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),sa=(a.defineLocale("es-do",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(a,b){return/-MMM-/.test(b)?ra[a.month()]:qa[a.month()]},monthsParseExact:!0,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY h:mm A",LLLL:"dddd, D [de] MMMM [de] YYYY h:mm A"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,// Monday is the first day of the week. +doy:4}}),"ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_")),ta="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),ua=(a.defineLocale("es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(a,b){return/-MMM-/.test(b)?ta[a.month()]:sa[a.month()]},monthsParseExact:!0,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("et",{months:"jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"),monthsShort:"jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"),weekdays:"pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev".split("_"),weekdaysShort:"P_E_T_K_N_R_L".split("_"),weekdaysMin:"P_E_T_K_N_R_L".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[Täna,] LT",nextDay:"[Homme,] LT",nextWeek:"[Järgmine] dddd LT",lastDay:"[Eile,] LT",lastWeek:"[Eelmine] dddd LT",sameElse:"L"},relativeTime:{future:"%s pärast",past:"%s tagasi",s:o,m:o,mm:o,h:o,hh:o,d:o,dd:"%d päeva",M:o,MM:o,y:o,yy:o},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("eu",{months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),monthsParseExact:!0,weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY[ko] MMMM[ren] D[a]",LLL:"YYYY[ko] MMMM[ren] D[a] HH:mm",LLLL:"dddd, YYYY[ko] MMMM[ren] D[a] HH:mm",l:"YYYY-M-D",ll:"YYYY[ko] MMM D[a]",lll:"YYYY[ko] MMM D[a] HH:mm",llll:"ddd, YYYY[ko] MMM D[a] HH:mm"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),{1:"۱",2:"۲",3:"۳",4:"۴",5:"۵",6:"۶",7:"۷",8:"۸",9:"۹",0:"۰"}),va={"۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9","۰":"0"},wa=(a.defineLocale("fa",{months:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),monthsShort:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),weekdays:"یکشنبه_دوشنبه_سهشنبه_چهارشنبه_پنجشنبه_جمعه_شنبه".split("_"),weekdaysShort:"یکشنبه_دوشنبه_سهشنبه_چهارشنبه_پنجشنبه_جمعه_شنبه".split("_"),weekdaysMin:"ی_د_س_چ_پ_ج_ش".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/قبل از ظهر|بعد از ظهر/,isPM:function(a){return/بعد از ظهر/.test(a)},meridiem:function(a,b,c){return 12>a?"قبل از ظهر":"بعد از ظهر"},calendar:{sameDay:"[امروز ساعت] LT",nextDay:"[فردا ساعت] LT",nextWeek:"dddd [ساعت] LT",lastDay:"[دیروز ساعت] LT",lastWeek:"dddd [پیش] [ساعت] LT",sameElse:"L"},relativeTime:{future:"در %s",past:"%s پیش",s:"چندین ثانیه",m:"یک دقیقه",mm:"%d دقیقه",h:"یک ساعت",hh:"%d ساعت",d:"یک روز",dd:"%d روز",M:"یک ماه",MM:"%d ماه",y:"یک سال",yy:"%d سال"},preparse:function(a){return a.replace(/[۰-۹]/g,function(a){return va[a]}).replace(/،/g,",")},postformat:function(a){return a.replace(/\d/g,function(a){return ua[a]}).replace(/,/g,"،")},ordinalParse:/\d{1,2}م/,ordinal:"%dم",week:{dow:6,// Saturday is the first day of the week. +doy:12}}),"nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän".split(" ")),xa=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",wa[7],wa[8],wa[9]],ya=(a.defineLocale("fi",{months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"Do MMMM[ta] YYYY",LLL:"Do MMMM[ta] YYYY, [klo] HH.mm",LLLL:"dddd, Do MMMM[ta] YYYY, [klo] HH.mm",l:"D.M.YYYY",ll:"Do MMM YYYY",lll:"Do MMM YYYY, [klo] HH.mm",llll:"ddd, Do MMM YYYY, [klo] HH.mm"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s:p,m:p,mm:p,h:p,hh:p,d:p,dd:p,M:p,MM:p,y:p,yy:p},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("fo",{months:"januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur".split("_"),weekdaysShort:"sun_mán_týs_mik_hós_frí_ley".split("_"),weekdaysMin:"su_má_tý_mi_hó_fr_le".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D. MMMM, YYYY HH:mm"},calendar:{sameDay:"[Í dag kl.] LT",nextDay:"[Í morgin kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[Í gjár kl.] LT",lastWeek:"[síðstu] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"um %s",past:"%s síðani",s:"fá sekund",m:"ein minutt",mm:"%d minuttir",h:"ein tími",hh:"%d tímar",d:"ein dagur",dd:"%d dagar",M:"ein mánaði",MM:"%d mánaðir",y:"eitt ár",yy:"%d ár"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("fr-ca",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinalParse:/\d{1,2}(er|e)/,ordinal:function(a){return a+(1===a?"er":"e")}}),a.defineLocale("fr-ch",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinalParse:/\d{1,2}(er|e)/,ordinal:function(a){return a+(1===a?"er":"e")},week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinalParse:/\d{1,2}(er|)/,ordinal:function(a){return a+(1===a?"er":"")},week:{dow:1,// Monday is the first day of the week. +doy:4}}),"jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.".split("_")),za="jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),Aa=(a.defineLocale("fy",{months:"jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber".split("_"),monthsShort:function(a,b){return/-MMM-/.test(b)?za[a.month()]:ya[a.month()]},monthsParseExact:!0,weekdays:"snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon".split("_"),weekdaysShort:"si._mo._ti._wo._to._fr._so.".split("_"),weekdaysMin:"Si_Mo_Ti_Wo_To_Fr_So".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[hjoed om] LT",nextDay:"[moarn om] LT",nextWeek:"dddd [om] LT",lastDay:"[juster om] LT",lastWeek:"[ôfrûne] dddd [om] LT",sameElse:"L"},relativeTime:{future:"oer %s",past:"%s lyn",s:"in pear sekonden",m:"ien minút",mm:"%d minuten",h:"ien oere",hh:"%d oeren",d:"ien dei",dd:"%d dagen",M:"ien moanne",MM:"%d moannen",y:"ien jier",yy:"%d jierren"},ordinalParse:/\d{1,2}(ste|de)/,ordinal:function(a){return a+(1===a||8===a||a>=20?"ste":"de")},week:{dow:1,// Monday is the first day of the week. +doy:4}}),["Am Faoilleach","An Gearran","Am Màrt","An Giblean","An Cèitean","An t-Ògmhios","An t-Iuchar","An Lùnastal","An t-Sultain","An Dàmhair","An t-Samhain","An Dùbhlachd"]),Ba=["Faoi","Gear","Màrt","Gibl","Cèit","Ògmh","Iuch","Lùn","Sult","Dàmh","Samh","Dùbh"],Ca=["Didòmhnaich","Diluain","Dimàirt","Diciadain","Diardaoin","Dihaoine","Disathairne"],Da=["Did","Dil","Dim","Dic","Dia","Dih","Dis"],Ea=["Dò","Lu","Mà","Ci","Ar","Ha","Sa"],Fa=(a.defineLocale("gd",{months:Aa,monthsShort:Ba,monthsParseExact:!0,weekdays:Ca,weekdaysShort:Da,weekdaysMin:Ea,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[An-diugh aig] LT",nextDay:"[A-màireach aig] LT",nextWeek:"dddd [aig] LT",lastDay:"[An-dè aig] LT",lastWeek:"dddd [seo chaidh] [aig] LT",sameElse:"L"},relativeTime:{future:"ann an %s",past:"bho chionn %s",s:"beagan diogan",m:"mionaid",mm:"%d mionaidean",h:"uair",hh:"%d uairean",d:"latha",dd:"%d latha",M:"mìos",MM:"%d mìosan",y:"bliadhna",yy:"%d bliadhna"},ordinalParse:/\d{1,2}(d|na|mh)/,ordinal:function(a){var b=1===a?"d":a%10===2?"na":"mh";return a+b},week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("gl",{months:"Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro".split("_"),monthsShort:"Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"),monthsParseExact:!0,weekdays:"Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"),weekdaysShort:"Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd D MMMM YYYY H:mm"},calendar:{sameDay:function(){return"[hoxe "+(1!==this.hours()?"ás":"á")+"] LT"},nextDay:function(){return"[mañá "+(1!==this.hours()?"ás":"á")+"] LT"},nextWeek:function(){return"dddd ["+(1!==this.hours()?"ás":"a")+"] LT"},lastDay:function(){return"[onte "+(1!==this.hours()?"á":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(1!==this.hours()?"ás":"a")+"] LT"},sameElse:"L"},relativeTime:{future:function(a){return"uns segundos"===a?"nuns segundos":"en "+a},past:"hai %s",s:"uns segundos",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("he",{months:"ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר".split("_"),monthsShort:"ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳".split("_"),weekdays:"ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת".split("_"),weekdaysShort:"א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"),weekdaysMin:"א_ב_ג_ד_ה_ו_ש".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [ב]MMMM YYYY",LLL:"D [ב]MMMM YYYY HH:mm",LLLL:"dddd, D [ב]MMMM YYYY HH:mm",l:"D/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[היום ב־]LT",nextDay:"[מחר ב־]LT",nextWeek:"dddd [בשעה] LT",lastDay:"[אתמול ב־]LT",lastWeek:"[ביום] dddd [האחרון בשעה] LT",sameElse:"L"},relativeTime:{future:"בעוד %s",past:"לפני %s",s:"מספר שניות",m:"דקה",mm:"%d דקות",h:"שעה",hh:function(a){return 2===a?"שעתיים":a+" שעות"},d:"יום",dd:function(a){return 2===a?"יומיים":a+" ימים"},M:"חודש",MM:function(a){return 2===a?"חודשיים":a+" חודשים"},y:"שנה",yy:function(a){return 2===a?"שנתיים":a%10===0&&10!==a?a+" שנה":a+" שנים"}},meridiemParse:/אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,isPM:function(a){return/^(אחה"צ|אחרי הצהריים|בערב)$/.test(a)},meridiem:function(a,b,c){return 5>a?"לפנות בוקר":10>a?"בבוקר":12>a?c?'לפנה"צ':"לפני הצהריים":18>a?c?'אחה"צ':"אחרי הצהריים":"בערב"}}),{1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"}),Ga={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"},Ha=(a.defineLocale("hi",{months:"जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर".split("_"),monthsShort:"जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.".split("_"),monthsParseExact:!0,weekdays:"रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm बजे",LTS:"A h:mm:ss बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm बजे",LLLL:"dddd, D MMMM YYYY, A h:mm बजे"},calendar:{sameDay:"[आज] LT",nextDay:"[कल] LT",nextWeek:"dddd, LT",lastDay:"[कल] LT",lastWeek:"[पिछले] dddd, LT",sameElse:"L"},relativeTime:{future:"%s में",past:"%s पहले",s:"कुछ ही क्षण",m:"एक मिनट",mm:"%d मिनट",h:"एक घंटा",hh:"%d घंटे",d:"एक दिन",dd:"%d दिन",M:"एक महीने",MM:"%d महीने",y:"एक वर्ष",yy:"%d वर्ष"},preparse:function(a){return a.replace(/[१२३४५६७८९०]/g,function(a){return Ga[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return Fa[a]})}, +// Hindi notation for meridiems are quite fuzzy in practice. While there exists +// a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi. +meridiemParse:/रात|सुबह|दोपहर|शाम/,meridiemHour:function(a,b){return 12===a&&(a=0),"रात"===b?4>a?a:a+12:"सुबह"===b?a:"दोपहर"===b?a>=10?a:a+12:"शाम"===b?a+12:void 0},meridiem:function(a,b,c){return 4>a?"रात":10>a?"सुबह":17>a?"दोपहर":20>a?"शाम":"रात"},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),a.defineLocale("hr",{months:{format:"siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca".split("_"),standalone:"siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_")},monthsShort:"sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",m:r,mm:r,h:r,hh:r,d:"dan",dd:r,M:"mjesec",MM:r,y:"godinu",yy:r},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),"vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton".split(" ")),Ia=(a.defineLocale("hu",{months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),weekdays:"vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"vas_hét_kedd_sze_csüt_pén_szo".split("_"),weekdaysMin:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D. H:mm",LLLL:"YYYY. MMMM D., dddd H:mm"},meridiemParse:/de|du/i,isPM:function(a){return"u"===a.charAt(1).toLowerCase()},meridiem:function(a,b,c){return 12>a?c===!0?"de":"DE":c===!0?"du":"DU"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return t.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return t.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:s,m:s,mm:s,h:s,hh:s,d:s,dd:s,M:s,MM:s,y:s,yy:s},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("hy-am",{months:{format:"հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի".split("_"),standalone:"հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր".split("_")},monthsShort:"հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ".split("_"),weekdays:"կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ".split("_"),weekdaysShort:"կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),weekdaysMin:"կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY թ.",LLL:"D MMMM YYYY թ., HH:mm",LLLL:"dddd, D MMMM YYYY թ., HH:mm"},calendar:{sameDay:"[այսօր] LT",nextDay:"[վաղը] LT",lastDay:"[երեկ] LT",nextWeek:function(){return"dddd [օրը ժամը] LT"},lastWeek:function(){return"[անցած] dddd [օրը ժամը] LT"},sameElse:"L"},relativeTime:{future:"%s հետո",past:"%s առաջ",s:"մի քանի վայրկյան",m:"րոպե",mm:"%d րոպե",h:"ժամ",hh:"%d ժամ",d:"օր",dd:"%d օր",M:"ամիս",MM:"%d ամիս",y:"տարի",yy:"%d տարի"},meridiemParse:/գիշերվա|առավոտվա|ցերեկվա|երեկոյան/,isPM:function(a){return/^(ցերեկվա|երեկոյան)$/.test(a)},meridiem:function(a){return 4>a?"գիշերվա":12>a?"առավոտվա":17>a?"ցերեկվա":"երեկոյան"},ordinalParse:/\d{1,2}|\d{1,2}-(ին|րդ)/,ordinal:function(a,b){switch(b){case"DDD":case"w":case"W":case"DDDo":return 1===a?a+"-ին":a+"-րդ";default:return a}},week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|siang|sore|malam/,meridiemHour:function(a,b){return 12===a&&(a=0),"pagi"===b?a:"siang"===b?a>=11?a:a+12:"sore"===b||"malam"===b?a+12:void 0},meridiem:function(a,b,c){return 11>a?"pagi":15>a?"siang":19>a?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("is",{months:"janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),monthsShort:"jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),weekdays:"sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),weekdaysShort:"sun_mán_þri_mið_fim_fös_lau".split("_"),weekdaysMin:"Su_Má_Þr_Mi_Fi_Fö_La".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd, D. MMMM YYYY [kl.] H:mm"},calendar:{sameDay:"[í dag kl.] LT",nextDay:"[á morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[í gær kl.] LT",lastWeek:"[síðasta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s síðan",s:v,m:v,mm:v,h:"klukkustund",hh:v,d:v,dd:v,M:v,MM:v,y:v,yy:v},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("it",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),weekdaysShort:"Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),weekdaysMin:"Do_Lu_Ma_Me_Gi_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:function(){switch(this.day()){case 0:return"[la scorsa] dddd [alle] LT";default:return"[lo scorso] dddd [alle] LT"}},sameElse:"L"},relativeTime:{future:function(a){return(/^[0-9].+$/.test(a)?"tra":"in")+" "+a},past:"%s fa",s:"alcuni secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("ja",{months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",LTS:"Ah時m分s秒",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日Ah時m分",LLLL:"YYYY年M月D日Ah時m分 dddd"},meridiemParse:/午前|午後/i,isPM:function(a){return"午後"===a},meridiem:function(a,b,c){return 12>a?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},ordinalParse:/\d{1,2}日/,ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"日";default:return a}},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"}}),a.defineLocale("jv",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des".split("_"),weekdays:"Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu".split("_"),weekdaysShort:"Min_Sen_Sel_Reb_Kem_Jem_Sep".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sp".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/enjing|siyang|sonten|ndalu/,meridiemHour:function(a,b){return 12===a&&(a=0),"enjing"===b?a:"siyang"===b?a>=11?a:a+12:"sonten"===b||"ndalu"===b?a+12:void 0},meridiem:function(a,b,c){return 11>a?"enjing":15>a?"siyang":19>a?"sonten":"ndalu"},calendar:{sameDay:"[Dinten puniko pukul] LT",nextDay:"[Mbenjang pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kala wingi pukul] LT",lastWeek:"dddd [kepengker pukul] LT",sameElse:"L"},relativeTime:{future:"wonten ing %s",past:"%s ingkang kepengker",s:"sawetawis detik",m:"setunggal menit",mm:"%d menit",h:"setunggal jam",hh:"%d jam",d:"sedinten",dd:"%d dinten",M:"sewulan",MM:"%d wulan",y:"setaun",yy:"%d taun"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("ka",{months:{standalone:"იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი".split("_"),format:"იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს".split("_")},monthsShort:"იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ".split("_"),weekdays:{standalone:"კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი".split("_"),format:"კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს".split("_"),isFormat:/(წინა|შემდეგ)/},weekdaysShort:"კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ".split("_"),weekdaysMin:"კვ_ორ_სა_ოთ_ხუ_პა_შა".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[დღეს] LT[-ზე]",nextDay:"[ხვალ] LT[-ზე]",lastDay:"[გუშინ] LT[-ზე]",nextWeek:"[შემდეგ] dddd LT[-ზე]",lastWeek:"[წინა] dddd LT-ზე",sameElse:"L"},relativeTime:{future:function(a){return/(წამი|წუთი|საათი|წელი)/.test(a)?a.replace(/ი$/,"ში"):a+"ში"},past:function(a){return/(წამი|წუთი|საათი|დღე|თვე)/.test(a)?a.replace(/(ი|ე)$/,"ის წინ"):/წელი/.test(a)?a.replace(/წელი$/,"წლის წინ"):void 0},s:"რამდენიმე წამი",m:"წუთი",mm:"%d წუთი",h:"საათი",hh:"%d საათი",d:"დღე",dd:"%d დღე",M:"თვე",MM:"%d თვე",y:"წელი",yy:"%d წელი"},ordinalParse:/0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/,ordinal:function(a){return 0===a?a:1===a?a+"-ლი":20>a||100>=a&&a%20===0||a%100===0?"მე-"+a:a+"-ე"},week:{dow:1,doy:7}}),{0:"-ші",1:"-ші",2:"-ші",3:"-ші",4:"-ші",5:"-ші",6:"-шы",7:"-ші",8:"-ші",9:"-шы",10:"-шы",20:"-шы",30:"-шы",40:"-шы",50:"-ші",60:"-шы",70:"-ші",80:"-ші",90:"-шы",100:"-ші"}),Ja=(a.defineLocale("kk",{months:"қаңтар_ақпан_наурыз_сәуір_мамыр_маусым_шілде_тамыз_қыркүйек_қазан_қараша_желтоқсан".split("_"),monthsShort:"қаң_ақп_нау_сәу_мам_мау_шіл_там_қыр_қаз_қар_жел".split("_"),weekdays:"жексенбі_дүйсенбі_сейсенбі_сәрсенбі_бейсенбі_жұма_сенбі".split("_"),weekdaysShort:"жек_дүй_сей_сәр_бей_жұм_сен".split("_"),weekdaysMin:"жк_дй_сй_ср_бй_жм_сн".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Бүгін сағат] LT",nextDay:"[Ертең сағат] LT",nextWeek:"dddd [сағат] LT",lastDay:"[Кеше сағат] LT",lastWeek:"[Өткен аптаның] dddd [сағат] LT",sameElse:"L"},relativeTime:{future:"%s ішінде",past:"%s бұрын",s:"бірнеше секунд",m:"бір минут",mm:"%d минут",h:"бір сағат",hh:"%d сағат",d:"бір күн",dd:"%d күн",M:"бір ай",MM:"%d ай",y:"бір жыл",yy:"%d жыл"},ordinalParse:/\d{1,2}-(ші|шы)/,ordinal:function(a){var b=a%10,c=a>=100?100:null;return a+(Ia[a]||Ia[b]||Ia[c])},week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("km",{months:"មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ".split("_"),monthsShort:"មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ".split("_"),weekdays:"អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍".split("_"),weekdaysShort:"អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍".split("_"),weekdaysMin:"អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[ថ្ងៃនេះ ម៉ោង] LT",nextDay:"[ស្អែក ម៉ោង] LT",nextWeek:"dddd [ម៉ោង] LT",lastDay:"[ម្សិលមិញ ម៉ោង] LT",lastWeek:"dddd [សប្តាហ៍មុន] [ម៉ោង] LT",sameElse:"L"},relativeTime:{future:"%sទៀត",past:"%sមុន",s:"ប៉ុន្មានវិនាទី",m:"មួយនាទី",mm:"%d នាទី",h:"មួយម៉ោង",hh:"%d ម៉ោង",d:"មួយថ្ងៃ",dd:"%d ថ្ងៃ",M:"មួយខែ",MM:"%d ខែ",y:"មួយឆ្នាំ",yy:"%d ឆ្នាំ"},week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("ko",{months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h시 m분",LTS:"A h시 m분 s초",L:"YYYY.MM.DD",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 A h시 m분",LLLL:"YYYY년 MMMM D일 dddd A h시 m분"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇 초",ss:"%d초",m:"일분",mm:"%d분",h:"한 시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한 달",MM:"%d달",y:"일 년",yy:"%d년"},ordinalParse:/\d{1,2}일/,ordinal:"%d일",meridiemParse:/오전|오후/,isPM:function(a){return"오후"===a},meridiem:function(a,b,c){return 12>a?"오전":"오후"}}),{0:"-чү",1:"-чи",2:"-чи",3:"-чү",4:"-чү",5:"-чи",6:"-чы",7:"-чи",8:"-чи",9:"-чу",10:"-чу",20:"-чы",30:"-чу",40:"-чы",50:"-чү",60:"-чы",70:"-чи",80:"-чи",90:"-чу",100:"-чү"}),Ka=(a.defineLocale("ky",{months:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_"),monthsShort:"янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек".split("_"),weekdays:"Жекшемби_Дүйшөмбү_Шейшемби_Шаршемби_Бейшемби_Жума_Ишемби".split("_"),weekdaysShort:"Жек_Дүй_Шей_Шар_Бей_Жум_Ише".split("_"),weekdaysMin:"Жк_Дй_Шй_Шр_Бй_Жм_Иш".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Бүгүн саат] LT",nextDay:"[Эртең саат] LT",nextWeek:"dddd [саат] LT",lastDay:"[Кече саат] LT",lastWeek:"[Өткен аптанын] dddd [күнү] [саат] LT",sameElse:"L"},relativeTime:{future:"%s ичинде",past:"%s мурун",s:"бирнече секунд",m:"бир мүнөт",mm:"%d мүнөт",h:"бир саат",hh:"%d саат",d:"бир күн",dd:"%d күн",M:"бир ай",MM:"%d ай",y:"бир жыл",yy:"%d жыл"},ordinalParse:/\d{1,2}-(чи|чы|чү|чу)/,ordinal:function(a){var b=a%10,c=a>=100?100:null;return a+(Ja[a]||Ja[b]||Ja[c])},week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("lb",{months:"Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg".split("_"),weekdaysShort:"So._Mé._Dë._Më._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mé_Dë_Më_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm [Auer]",LTS:"H:mm:ss [Auer]",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm [Auer]",LLLL:"dddd, D. MMMM YYYY H:mm [Auer]"},calendar:{sameDay:"[Haut um] LT",sameElse:"L",nextDay:"[Muer um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gëschter um] LT",lastWeek:function(){ +// Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule +switch(this.day()){case 2:case 4:return"[Leschten] dddd [um] LT";default:return"[Leschte] dddd [um] LT"}}},relativeTime:{future:x,past:y,s:"e puer Sekonnen",m:w,mm:"%d Minutten",h:w,hh:"%d Stonnen",d:w,dd:"%d Deeg",M:w,MM:"%d Méint",y:w,yy:"%d Joer"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("lo",{months:"ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ".split("_"),monthsShort:"ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ".split("_"),weekdays:"ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ".split("_"),weekdaysShort:"ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ".split("_"),weekdaysMin:"ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"ວັນdddd D MMMM YYYY HH:mm"},meridiemParse:/ຕອນເຊົ້າ|ຕອນແລງ/,isPM:function(a){return"ຕອນແລງ"===a},meridiem:function(a,b,c){return 12>a?"ຕອນເຊົ້າ":"ຕອນແລງ"},calendar:{sameDay:"[ມື້ນີ້ເວລາ] LT",nextDay:"[ມື້ອື່ນເວລາ] LT",nextWeek:"[ວັນ]dddd[ໜ້າເວລາ] LT",lastDay:"[ມື້ວານນີ້ເວລາ] LT",lastWeek:"[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT",sameElse:"L"},relativeTime:{future:"ອີກ %s",past:"%sຜ່ານມາ",s:"ບໍ່ເທົ່າໃດວິນາທີ",m:"1 ນາທີ",mm:"%d ນາທີ",h:"1 ຊົ່ວໂມງ",hh:"%d ຊົ່ວໂມງ",d:"1 ມື້",dd:"%d ມື້",M:"1 ເດືອນ",MM:"%d ເດືອນ",y:"1 ປີ",yy:"%d ປີ"},ordinalParse:/(ທີ່)\d{1,2}/,ordinal:function(a){return"ທີ່"+a}}),{m:"minutė_minutės_minutę",mm:"minutės_minučių_minutes",h:"valanda_valandos_valandą",hh:"valandos_valandų_valandas",d:"diena_dienos_dieną",dd:"dienos_dienų_dienas",M:"mėnuo_mėnesio_mėnesį",MM:"mėnesiai_mėnesių_mėnesius",y:"metai_metų_metus",yy:"metai_metų_metus"}),La=(a.defineLocale("lt",{months:{format:"sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio".split("_"),standalone:"sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis".split("_"),isFormat:/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?|MMMM?(\[[^\[\]]*\]|\s+)+D[oD]?/},monthsShort:"sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd".split("_"),weekdays:{format:"sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį".split("_"),standalone:"sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis".split("_"),isFormat:/dddd HH:mm/},weekdaysShort:"Sek_Pir_Ant_Tre_Ket_Pen_Šeš".split("_"),weekdaysMin:"S_P_A_T_K_Pn_Š".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY [m.] MMMM D [d.]",LLL:"YYYY [m.] MMMM D [d.], HH:mm [val.]",LLLL:"YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]",l:"YYYY-MM-DD",ll:"YYYY [m.] MMMM D [d.]",lll:"YYYY [m.] MMMM D [d.], HH:mm [val.]",llll:"YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]"},calendar:{sameDay:"[Šiandien] LT",nextDay:"[Rytoj] LT",nextWeek:"dddd LT",lastDay:"[Vakar] LT",lastWeek:"[Praėjusį] dddd LT",sameElse:"L"},relativeTime:{future:"po %s",past:"prieš %s",s:A,m:B,mm:E,h:B,hh:E,d:B,dd:E,M:B,MM:E,y:B,yy:E},ordinalParse:/\d{1,2}-oji/,ordinal:function(a){return a+"-oji"},week:{dow:1,// Monday is the first day of the week. +doy:4}}),{m:"minūtes_minūtēm_minūte_minūtes".split("_"),mm:"minūtes_minūtēm_minūte_minūtes".split("_"),h:"stundas_stundām_stunda_stundas".split("_"),hh:"stundas_stundām_stunda_stundas".split("_"),d:"dienas_dienām_diena_dienas".split("_"),dd:"dienas_dienām_diena_dienas".split("_"),M:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),MM:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),y:"gada_gadiem_gads_gadi".split("_"),yy:"gada_gadiem_gads_gadi".split("_")}),Ma=(a.defineLocale("lv",{months:"janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris".split("_"),monthsShort:"jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec".split("_"),weekdays:"svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena".split("_"),weekdaysShort:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysMin:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY.",LL:"YYYY. [gada] D. MMMM",LLL:"YYYY. [gada] D. MMMM, HH:mm",LLLL:"YYYY. [gada] D. MMMM, dddd, HH:mm"},calendar:{sameDay:"[Šodien pulksten] LT",nextDay:"[Rīt pulksten] LT",nextWeek:"dddd [pulksten] LT",lastDay:"[Vakar pulksten] LT",lastWeek:"[Pagājušā] dddd [pulksten] LT",sameElse:"L"},relativeTime:{future:"pēc %s",past:"pirms %s",s:I,m:H,mm:G,h:H,hh:G,d:H,dd:G,M:H,MM:G,y:H,yy:G},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),{words:{//Different grammatical cases +m:["jedan minut","jednog minuta"],mm:["minut","minuta","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],dd:["dan","dana","dana"],MM:["mjesec","mjeseca","mjeseci"],yy:["godina","godine","godina"]},correctGrammaticalCase:function(a,b){return 1===a?b[0]:a>=2&&4>=a?b[1]:b[2]},translate:function(a,b,c){var d=Ma.words[c];return 1===c.length?b?d[0]:d[1]:a+" "+Ma.correctGrammaticalCase(a,d)}}),Na=(a.defineLocale("me",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sjutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){var a=["[prošle] [nedjelje] [u] LT","[prošlog] [ponedjeljka] [u] LT","[prošlog] [utorka] [u] LT","[prošle] [srijede] [u] LT","[prošlog] [četvrtka] [u] LT","[prošlog] [petka] [u] LT","[prošle] [subote] [u] LT"];return a[this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"nekoliko sekundi",m:Ma.translate,mm:Ma.translate,h:Ma.translate,hh:Ma.translate,d:"dan",dd:Ma.translate,M:"mjesec",MM:Ma.translate,y:"godinu",yy:Ma.translate},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("mk",{months:"јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември".split("_"),monthsShort:"јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек".split("_"),weekdays:"недела_понеделник_вторник_среда_четврток_петок_сабота".split("_"),weekdaysShort:"нед_пон_вто_сре_чет_пет_саб".split("_"),weekdaysMin:"нe_пo_вт_ср_че_пе_сa".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[Денес во] LT",nextDay:"[Утре во] LT",nextWeek:"[Во] dddd [во] LT",lastDay:"[Вчера во] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[Изминатата] dddd [во] LT";case 1:case 2:case 4:case 5:return"[Изминатиот] dddd [во] LT"}},sameElse:"L"},relativeTime:{future:"после %s",past:"пред %s",s:"неколку секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дена",M:"месец",MM:"%d месеци",y:"година",yy:"%d години"},ordinalParse:/\d{1,2}-(ев|ен|ти|ви|ри|ми)/,ordinal:function(a){var b=a%10,c=a%100;return 0===a?a+"-ев":0===c?a+"-ен":c>10&&20>c?a+"-ти":1===b?a+"-ви":2===b?a+"-ри":7===b||8===b?a+"-ми":a+"-ти"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("ml",{months:"ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ".split("_"),monthsShort:"ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.".split("_"),monthsParseExact:!0,weekdays:"ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച".split("_"),weekdaysShort:"ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി".split("_"),weekdaysMin:"ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ".split("_"),longDateFormat:{LT:"A h:mm -നു",LTS:"A h:mm:ss -നു",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm -നു",LLLL:"dddd, D MMMM YYYY, A h:mm -നു"},calendar:{sameDay:"[ഇന്ന്] LT",nextDay:"[നാളെ] LT",nextWeek:"dddd, LT",lastDay:"[ഇന്നലെ] LT",lastWeek:"[കഴിഞ്ഞ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s കഴിഞ്ഞ്",past:"%s മുൻപ്",s:"അൽപ നിമിഷങ്ങൾ",m:"ഒരു മിനിറ്റ്",mm:"%d മിനിറ്റ്",h:"ഒരു മണിക്കൂർ",hh:"%d മണിക്കൂർ",d:"ഒരു ദിവസം",dd:"%d ദിവസം",M:"ഒരു മാസം",MM:"%d മാസം",y:"ഒരു വർഷം",yy:"%d വർഷം"},meridiemParse:/രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i,meridiemHour:function(a,b){return 12===a&&(a=0),"രാത്രി"===b&&a>=4||"ഉച്ച കഴിഞ്ഞ്"===b||"വൈകുന്നേരം"===b?a+12:a},meridiem:function(a,b,c){return 4>a?"രാത്രി":12>a?"രാവിലെ":17>a?"ഉച്ച കഴിഞ്ഞ്":20>a?"വൈകുന്നേരം":"രാത്രി"}}),{1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"}),Oa={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"},Pa=(a.defineLocale("mr",{months:"जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर".split("_"),monthsShort:"जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.".split("_"),monthsParseExact:!0,weekdays:"रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm वाजता",LTS:"A h:mm:ss वाजता",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm वाजता",LLLL:"dddd, D MMMM YYYY, A h:mm वाजता"},calendar:{sameDay:"[आज] LT",nextDay:"[उद्या] LT",nextWeek:"dddd, LT",lastDay:"[काल] LT",lastWeek:"[मागील] dddd, LT",sameElse:"L"},relativeTime:{future:"%sमध्ये",past:"%sपूर्वी",s:J,m:J,mm:J,h:J,hh:J,d:J,dd:J,M:J,MM:J,y:J,yy:J},preparse:function(a){return a.replace(/[१२३४५६७८९०]/g,function(a){return Oa[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return Na[a]})},meridiemParse:/रात्री|सकाळी|दुपारी|सायंकाळी/,meridiemHour:function(a,b){return 12===a&&(a=0),"रात्री"===b?4>a?a:a+12:"सकाळी"===b?a:"दुपारी"===b?a>=10?a:a+12:"सायंकाळी"===b?a+12:void 0},meridiem:function(a,b,c){return 4>a?"रात्री":10>a?"सकाळी":17>a?"दुपारी":20>a?"सायंकाळी":"रात्री"},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),a.defineLocale("ms-my",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|tengahari|petang|malam/,meridiemHour:function(a,b){return 12===a&&(a=0),"pagi"===b?a:"tengahari"===b?a>=11?a:a+12:"petang"===b||"malam"===b?a+12:void 0},meridiem:function(a,b,c){return 11>a?"pagi":15>a?"tengahari":19>a?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("ms",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|tengahari|petang|malam/,meridiemHour:function(a,b){return 12===a&&(a=0),"pagi"===b?a:"tengahari"===b?a>=11?a:a+12:"petang"===b||"malam"===b?a+12:void 0},meridiem:function(a,b,c){return 11>a?"pagi":15>a?"tengahari":19>a?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),{1:"၁",2:"၂",3:"၃",4:"၄",5:"၅",6:"၆",7:"၇",8:"၈",9:"၉",0:"၀"}),Qa={"၁":"1","၂":"2","၃":"3","၄":"4","၅":"5","၆":"6","၇":"7","၈":"8","၉":"9","၀":"0"},Ra=(a.defineLocale("my",{months:"ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ".split("_"),monthsShort:"ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ".split("_"),weekdays:"တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ".split("_"),weekdaysShort:"နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ".split("_"),weekdaysMin:"နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[ယနေ.] LT [မှာ]",nextDay:"[မနက်ဖြန်] LT [မှာ]",nextWeek:"dddd LT [မှာ]",lastDay:"[မနေ.က] LT [မှာ]",lastWeek:"[ပြီးခဲ့သော] dddd LT [မှာ]",sameElse:"L"},relativeTime:{future:"လာမည့် %s မှာ",past:"လွန်ခဲ့သော %s က",s:"စက္ကန်.အနည်းငယ်",m:"တစ်မိနစ်",mm:"%d မိနစ်",h:"တစ်နာရီ",hh:"%d နာရီ",d:"တစ်ရက်",dd:"%d ရက်",M:"တစ်လ",MM:"%d လ",y:"တစ်နှစ်",yy:"%d နှစ်"},preparse:function(a){return a.replace(/[၁၂၃၄၅၆၇၈၉၀]/g,function(a){return Qa[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return Pa[a]})},week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("nb",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.".split("_"),monthsParseExact:!0,weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"sø._ma._ti._on._to._fr._lø.".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] HH:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[i går kl.] LT",lastWeek:"[forrige] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"noen sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en måned",MM:"%d måneder",y:"ett år",yy:"%d år"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),{1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"}),Sa={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"},Ta=(a.defineLocale("ne",{months:"जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर".split("_"),monthsShort:"जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.".split("_"),monthsParseExact:!0,weekdays:"आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार".split("_"),weekdaysShort:"आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.".split("_"),weekdaysMin:"आ._सो._मं._बु._बि._शु._श.".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"Aको h:mm बजे",LTS:"Aको h:mm:ss बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, Aको h:mm बजे",LLLL:"dddd, D MMMM YYYY, Aको h:mm बजे"},preparse:function(a){return a.replace(/[१२३४५६७८९०]/g,function(a){return Sa[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return Ra[a]})},meridiemParse:/राति|बिहान|दिउँसो|साँझ/,meridiemHour:function(a,b){return 12===a&&(a=0),"राति"===b?4>a?a:a+12:"बिहान"===b?a:"दिउँसो"===b?a>=10?a:a+12:"साँझ"===b?a+12:void 0},meridiem:function(a,b,c){return 3>a?"राति":12>a?"बिहान":16>a?"दिउँसो":20>a?"साँझ":"राति"},calendar:{sameDay:"[आज] LT",nextDay:"[भोलि] LT",nextWeek:"[आउँदो] dddd[,] LT",lastDay:"[हिजो] LT",lastWeek:"[गएको] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%sमा",past:"%s अगाडि",s:"केही क्षण",m:"एक मिनेट",mm:"%d मिनेट",h:"एक घण्टा",hh:"%d घण्टा",d:"एक दिन",dd:"%d दिन",M:"एक महिना",MM:"%d महिना",y:"एक बर्ष",yy:"%d बर्ष"},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),"jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_")),Ua="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),Va=(a.defineLocale("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(a,b){return/-MMM-/.test(b)?Ua[a.month()]:Ta[a.month()]},monthsParseExact:!0,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},ordinalParse:/\d{1,2}(ste|de)/,ordinal:function(a){return a+(1===a||8===a||a>=20?"ste":"de")},week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("nn",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),weekdaysShort:"sun_mån_tys_ons_tor_fre_lau".split("_"),weekdaysMin:"su_må_ty_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[I dag klokka] LT",nextDay:"[I morgon klokka] LT",nextWeek:"dddd [klokka] LT",lastDay:"[I går klokka] LT",lastWeek:"[Føregåande] dddd [klokka] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s sidan",s:"nokre sekund",m:"eit minutt",mm:"%d minutt",h:"ein time",hh:"%d timar",d:"ein dag",dd:"%d dagar",M:"ein månad",MM:"%d månader",y:"eit år",yy:"%d år"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),{1:"੧",2:"੨",3:"੩",4:"੪",5:"੫",6:"੬",7:"੭",8:"੮",9:"੯",0:"੦"}),Wa={"੧":"1","੨":"2","੩":"3","੪":"4","੫":"5","੬":"6","੭":"7","੮":"8","੯":"9","੦":"0"},Xa=(a.defineLocale("pa-in",{ +// There are months name as per Nanakshahi Calender but they are not used as rigidly in modern Punjabi. +months:"ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ".split("_"),monthsShort:"ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ".split("_"),weekdays:"ਐਤਵਾਰ_ਸੋਮਵਾਰ_ਮੰਗਲਵਾਰ_ਬੁਧਵਾਰ_ਵੀਰਵਾਰ_ਸ਼ੁੱਕਰਵਾਰ_ਸ਼ਨੀਚਰਵਾਰ".split("_"),weekdaysShort:"ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ".split("_"),weekdaysMin:"ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ".split("_"),longDateFormat:{LT:"A h:mm ਵਜੇ",LTS:"A h:mm:ss ਵਜੇ",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm ਵਜੇ",LLLL:"dddd, D MMMM YYYY, A h:mm ਵਜੇ"},calendar:{sameDay:"[ਅਜ] LT",nextDay:"[ਕਲ] LT",nextWeek:"dddd, LT",lastDay:"[ਕਲ] LT",lastWeek:"[ਪਿਛਲੇ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s ਵਿੱਚ",past:"%s ਪਿਛਲੇ",s:"ਕੁਝ ਸਕਿੰਟ",m:"ਇਕ ਮਿੰਟ",mm:"%d ਮਿੰਟ",h:"ਇੱਕ ਘੰਟਾ",hh:"%d ਘੰਟੇ",d:"ਇੱਕ ਦਿਨ",dd:"%d ਦਿਨ",M:"ਇੱਕ ਮਹੀਨਾ",MM:"%d ਮਹੀਨੇ",y:"ਇੱਕ ਸਾਲ",yy:"%d ਸਾਲ"},preparse:function(a){return a.replace(/[੧੨੩੪੫੬੭੮੯੦]/g,function(a){return Wa[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return Va[a]})}, +// Punjabi notation for meridiems are quite fuzzy in practice. While there exists +// a rigid notion of a 'Pahar' it is not used as rigidly in modern Punjabi. +meridiemParse:/ਰਾਤ|ਸਵੇਰ|ਦੁਪਹਿਰ|ਸ਼ਾਮ/,meridiemHour:function(a,b){return 12===a&&(a=0),"ਰਾਤ"===b?4>a?a:a+12:"ਸਵੇਰ"===b?a:"ਦੁਪਹਿਰ"===b?a>=10?a:a+12:"ਸ਼ਾਮ"===b?a+12:void 0},meridiem:function(a,b,c){return 4>a?"ਰਾਤ":10>a?"ਸਵੇਰ":17>a?"ਦੁਪਹਿਰ":20>a?"ਸ਼ਾਮ":"ਰਾਤ"},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),"styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_")),Ya="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_"),Za=(a.defineLocale("pl",{months:function(a,b){return""===b?"("+Ya[a.month()]+"|"+Xa[a.month()]+")":/D MMMM/.test(b)?Ya[a.month()]:Xa[a.month()]},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"nie_pon_wt_śr_czw_pt_sb".split("_"),weekdaysMin:"Nd_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:"[W] dddd [o] LT",lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zeszłą niedzielę o] LT";case 3:return"[W zeszłą środę o] LT";case 6:return"[W zeszłą sobotę o] LT";default:return"[W zeszły] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",m:L,mm:L,h:L,hh:L,d:"1 dzień",dd:"%d dni",M:"miesiąc",MM:L,y:"rok",yy:L},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("pt-br",{months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY [às] HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY [às] HH:mm"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){// Saturday + Sunday +return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"poucos segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº"}),a.defineLocale("pt",{months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-Feira_Terça-Feira_Quarta-Feira_Quinta-Feira_Sexta-Feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY HH:mm"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){// Saturday + Sunday +return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"há %s",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("ro",{months:"ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie".split("_"),monthsShort:"ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"duminică_luni_marți_miercuri_joi_vineri_sâmbătă".split("_"),weekdaysShort:"Dum_Lun_Mar_Mie_Joi_Vin_Sâm".split("_"),weekdaysMin:"Du_Lu_Ma_Mi_Jo_Vi_Sâ".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[azi la] LT",nextDay:"[mâine la] LT",nextWeek:"dddd [la] LT",lastDay:"[ieri la] LT",lastWeek:"[fosta] dddd [la] LT",sameElse:"L"},relativeTime:{future:"peste %s",past:"%s în urmă",s:"câteva secunde",m:"un minut",mm:M,h:"o oră",hh:M,d:"o zi",dd:M,M:"o lună",MM:M,y:"un an",yy:M},week:{dow:1,// Monday is the first day of the week. +doy:7}}),[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[йя]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i]),$a=(a.defineLocale("ru",{months:{format:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_"),standalone:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_")},monthsShort:{ +// по CLDR именно "июл." и "июн.", но какой смысл менять букву на точку ? +format:"янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.".split("_"),standalone:"янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.".split("_")},weekdays:{standalone:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),format:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_"),isFormat:/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/},weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:Za,longMonthsParse:Za,shortMonthsParse:Za, +// полные названия с падежами, по три буквы, для некоторых, по 4 буквы, сокращения с точкой и без точки +monthsRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i, +// копия предыдущего +monthsShortRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i, +// полные названия с падежами +monthsStrictRegex:/^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i, +// Выражение, которое соотвествует только сокращённым формам +monthsShortStrictRegex:/^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., HH:mm",LLLL:"dddd, D MMMM YYYY г., HH:mm"},calendar:{sameDay:"[Сегодня в] LT",nextDay:"[Завтра в] LT",lastDay:"[Вчера в] LT",nextWeek:function(a){if(a.week()===this.week())return 2===this.day()?"[Во] dddd [в] LT":"[В] dddd [в] LT";switch(this.day()){case 0:return"[В следующее] dddd [в] LT";case 1:case 2:case 4:return"[В следующий] dddd [в] LT";case 3:case 5:case 6:return"[В следующую] dddd [в] LT"}},lastWeek:function(a){if(a.week()===this.week())return 2===this.day()?"[Во] dddd [в] LT":"[В] dddd [в] LT";switch(this.day()){case 0:return"[В прошлое] dddd [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",m:O,mm:O,h:"час",hh:O,d:"день",dd:O,M:"месяц",MM:O,y:"год",yy:O},meridiemParse:/ночи|утра|дня|вечера/i,isPM:function(a){return/^(дня|вечера)$/.test(a)},meridiem:function(a,b,c){return 4>a?"ночи":12>a?"утра":17>a?"дня":"вечера"},ordinalParse:/\d{1,2}-(й|го|я)/,ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":return a+"-й";case"D":return a+"-го";case"w":case"W":return a+"-я";default:return a}},week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("se",{months:"ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu".split("_"),monthsShort:"ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov".split("_"),weekdays:"sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat".split("_"),weekdaysShort:"sotn_vuos_maŋ_gask_duor_bear_láv".split("_"),weekdaysMin:"s_v_m_g_d_b_L".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"MMMM D. [b.] YYYY",LLL:"MMMM D. [b.] YYYY [ti.] HH:mm",LLLL:"dddd, MMMM D. [b.] YYYY [ti.] HH:mm"},calendar:{sameDay:"[otne ti] LT",nextDay:"[ihttin ti] LT",nextWeek:"dddd [ti] LT",lastDay:"[ikte ti] LT",lastWeek:"[ovddit] dddd [ti] LT",sameElse:"L"},relativeTime:{future:"%s geažes",past:"maŋit %s",s:"moadde sekunddat",m:"okta minuhta",mm:"%d minuhtat",h:"okta diimmu",hh:"%d diimmut",d:"okta beaivi",dd:"%d beaivvit",M:"okta mánnu",MM:"%d mánut",y:"okta jahki",yy:"%d jagit"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("si",{months:"ජනවාරි_පෙබරවාරි_මාර්තු_අප්රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්".split("_"),monthsShort:"ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ".split("_"),weekdays:"ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා".split("_"),weekdaysShort:"ඉරි_සඳු_අඟ_බදා_බ්රහ_සිකු_සෙන".split("_"),weekdaysMin:"ඉ_ස_අ_බ_බ්ර_සි_සෙ".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"a h:mm",LTS:"a h:mm:ss",L:"YYYY/MM/DD",LL:"YYYY MMMM D",LLL:"YYYY MMMM D, a h:mm",LLLL:"YYYY MMMM D [වැනි] dddd, a h:mm:ss"},calendar:{sameDay:"[අද] LT[ට]",nextDay:"[හෙට] LT[ට]",nextWeek:"dddd LT[ට]",lastDay:"[ඊයේ] LT[ට]",lastWeek:"[පසුගිය] dddd LT[ට]",sameElse:"L"},relativeTime:{future:"%sකින්",past:"%sකට පෙර",s:"තත්පර කිහිපය",m:"මිනිත්තුව",mm:"මිනිත්තු %d",h:"පැය",hh:"පැය %d",d:"දිනය",dd:"දින %d",M:"මාසය",MM:"මාස %d",y:"වසර",yy:"වසර %d"},ordinalParse:/\d{1,2} වැනි/,ordinal:function(a){return a+" වැනි"},meridiemParse:/පෙර වරු|පස් වරු|පෙ.ව|ප.ව./,isPM:function(a){return"ප.ව."===a||"පස් වරු"===a},meridiem:function(a,b,c){return a>11?c?"ප.ව.":"පස් වරු":c?"පෙ.ව.":"පෙර වරු"}}),"január_február_marec_apríl_máj_jún_júl_august_september_október_november_december".split("_")),_a="jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec".split("_"),ab=(a.defineLocale("sk",{months:$a,monthsShort:_a,weekdays:"nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota".split("_"),weekdaysShort:"ne_po_ut_st_št_pi_so".split("_"),weekdaysMin:"ne_po_ut_st_št_pi_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm"},calendar:{sameDay:"[dnes o] LT",nextDay:"[zajtra o] LT",nextWeek:function(){switch(this.day()){case 0:return"[v nedeľu o] LT";case 1:case 2:return"[v] dddd [o] LT";case 3:return"[v stredu o] LT";case 4:return"[vo štvrtok o] LT";case 5:return"[v piatok o] LT";case 6:return"[v sobotu o] LT"}},lastDay:"[včera o] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulú nedeľu o] LT";case 1:case 2:return"[minulý] dddd [o] LT";case 3:return"[minulú stredu o] LT";case 4:case 5:return"[minulý] dddd [o] LT";case 6:return"[minulú sobotu o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pred %s",s:Q,m:Q,mm:Q,h:Q,hh:Q,d:Q,dd:Q,M:Q,MM:Q,y:Q,yy:Q},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("sl",{months:"januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota".split("_"),weekdaysShort:"ned._pon._tor._sre._čet._pet._sob.".split("_"),weekdaysMin:"ne_po_to_sr_če_pe_so".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danes ob] LT",nextDay:"[jutri ob] LT",nextWeek:function(){switch(this.day()){case 0:return"[v] [nedeljo] [ob] LT";case 3:return"[v] [sredo] [ob] LT";case 6:return"[v] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[v] dddd [ob] LT"}},lastDay:"[včeraj ob] LT",lastWeek:function(){switch(this.day()){case 0:return"[prejšnjo] [nedeljo] [ob] LT";case 3:return"[prejšnjo] [sredo] [ob] LT";case 6:return"[prejšnjo] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[prejšnji] dddd [ob] LT"}},sameElse:"L"},relativeTime:{future:"čez %s",past:"pred %s",s:R,m:R,mm:R,h:R,hh:R,d:R,dd:R,M:R,MM:R,y:R,yy:R},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("sq",{months:"Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor".split("_"),monthsShort:"Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj".split("_"),weekdays:"E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë".split("_"),weekdaysShort:"Die_Hën_Mar_Mër_Enj_Pre_Sht".split("_"),weekdaysMin:"D_H_Ma_Më_E_P_Sh".split("_"),weekdaysParseExact:!0,meridiemParse:/PD|MD/,isPM:function(a){return"M"===a.charAt(0)},meridiem:function(a,b,c){return 12>a?"PD":"MD"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Sot në] LT",nextDay:"[Nesër në] LT",nextWeek:"dddd [në] LT",lastDay:"[Dje në] LT",lastWeek:"dddd [e kaluar në] LT",sameElse:"L"},relativeTime:{future:"në %s",past:"%s më parë",s:"disa sekonda",m:"një minutë",mm:"%d minuta",h:"një orë",hh:"%d orë",d:"një ditë",dd:"%d ditë",M:"një muaj",MM:"%d muaj",y:"një vit",yy:"%d vite"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),{words:{//Different grammatical cases +m:["један минут","једне минуте"],mm:["минут","минуте","минута"],h:["један сат","једног сата"],hh:["сат","сата","сати"],dd:["дан","дана","дана"],MM:["месец","месеца","месеци"],yy:["година","године","година"]},correctGrammaticalCase:function(a,b){return 1===a?b[0]:a>=2&&4>=a?b[1]:b[2]},translate:function(a,b,c){var d=ab.words[c];return 1===c.length?b?d[0]:d[1]:a+" "+ab.correctGrammaticalCase(a,d)}}),bb=(a.defineLocale("sr-cyrl",{months:"јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар".split("_"),monthsShort:"јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.".split("_"),monthsParseExact:!0,weekdays:"недеља_понедељак_уторак_среда_четвртак_петак_субота".split("_"),weekdaysShort:"нед._пон._уто._сре._чет._пет._суб.".split("_"),weekdaysMin:"не_по_ут_ср_че_пе_су".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[данас у] LT",nextDay:"[сутра у] LT",nextWeek:function(){switch(this.day()){case 0:return"[у] [недељу] [у] LT";case 3:return"[у] [среду] [у] LT";case 6:return"[у] [суботу] [у] LT";case 1:case 2:case 4:case 5:return"[у] dddd [у] LT"}},lastDay:"[јуче у] LT",lastWeek:function(){var a=["[прошле] [недеље] [у] LT","[прошлог] [понедељка] [у] LT","[прошлог] [уторка] [у] LT","[прошле] [среде] [у] LT","[прошлог] [четвртка] [у] LT","[прошлог] [петка] [у] LT","[прошле] [суботе] [у] LT"];return a[this.day()]},sameElse:"L"},relativeTime:{future:"за %s",past:"пре %s",s:"неколико секунди",m:ab.translate,mm:ab.translate,h:ab.translate,hh:ab.translate,d:"дан",dd:ab.translate,M:"месец",MM:ab.translate,y:"годину",yy:ab.translate},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),{words:{//Different grammatical cases +m:["jedan minut","jedne minute"],mm:["minut","minute","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],dd:["dan","dana","dana"],MM:["mesec","meseca","meseci"],yy:["godina","godine","godina"]},correctGrammaticalCase:function(a,b){return 1===a?b[0]:a>=2&&4>=a?b[1]:b[2]},translate:function(a,b,c){var d=bb.words[c];return 1===c.length?b?d[0]:d[1]:a+" "+bb.correctGrammaticalCase(a,d)}}),cb=(a.defineLocale("sr",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sre._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedelju] [u] LT";case 3:return"[u] [sredu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){var a=["[prošle] [nedelje] [u] LT","[prošlog] [ponedeljka] [u] LT","[prošlog] [utorka] [u] LT","[prošle] [srede] [u] LT","[prošlog] [četvrtka] [u] LT","[prošlog] [petka] [u] LT","[prošle] [subote] [u] LT"];return a[this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"pre %s",s:"nekoliko sekundi",m:bb.translate,mm:bb.translate,h:bb.translate,hh:bb.translate,d:"dan",dd:bb.translate,M:"mesec",MM:bb.translate,y:"godinu",yy:bb.translate},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("ss",{months:"Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split("_"),monthsShort:"Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo".split("_"),weekdays:"Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo".split("_"),weekdaysShort:"Lis_Umb_Lsb_Les_Lsi_Lsh_Umg".split("_"),weekdaysMin:"Li_Us_Lb_Lt_Ls_Lh_Ug".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Namuhla nga] LT",nextDay:"[Kusasa nga] LT",nextWeek:"dddd [nga] LT",lastDay:"[Itolo nga] LT",lastWeek:"dddd [leliphelile] [nga] LT",sameElse:"L"},relativeTime:{future:"nga %s",past:"wenteka nga %s",s:"emizuzwana lomcane",m:"umzuzu",mm:"%d emizuzu",h:"lihora",hh:"%d emahora",d:"lilanga",dd:"%d emalanga",M:"inyanga",MM:"%d tinyanga",y:"umnyaka",yy:"%d iminyaka"},meridiemParse:/ekuseni|emini|entsambama|ebusuku/,meridiem:function(a,b,c){return 11>a?"ekuseni":15>a?"emini":19>a?"entsambama":"ebusuku"},meridiemHour:function(a,b){return 12===a&&(a=0),"ekuseni"===b?a:"emini"===b?a>=11?a:a+12:"entsambama"===b||"ebusuku"===b?0===a?0:a+12:void 0},ordinalParse:/\d{1,2}/,ordinal:"%d",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("sv",{months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),weekdaysShort:"sön_mån_tis_ons_tor_fre_lör".split("_"),weekdaysMin:"sö_må_ti_on_to_fr_lö".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [kl.] HH:mm",LLLL:"dddd D MMMM YYYY [kl.] HH:mm",lll:"D MMM YYYY HH:mm",llll:"ddd D MMM YYYY HH:mm"},calendar:{sameDay:"[Idag] LT",nextDay:"[Imorgon] LT",lastDay:"[Igår] LT",nextWeek:"[På] dddd LT",lastWeek:"[I] dddd[s] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"för %s sedan",s:"några sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en månad",MM:"%d månader",y:"ett år",yy:"%d år"},ordinalParse:/\d{1,2}(e|a)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"e":1===b?"a":2===b?"a":"e";return a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("sw",{months:"Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des".split("_"),weekdays:"Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi".split("_"),weekdaysShort:"Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos".split("_"),weekdaysMin:"J2_J3_J4_J5_Al_Ij_J1".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[leo saa] LT",nextDay:"[kesho saa] LT",nextWeek:"[wiki ijayo] dddd [saat] LT",lastDay:"[jana] LT",lastWeek:"[wiki iliyopita] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s baadaye",past:"tokea %s",s:"hivi punde",m:"dakika moja",mm:"dakika %d",h:"saa limoja",hh:"masaa %d",d:"siku moja",dd:"masiku %d",M:"mwezi mmoja",MM:"miezi %d",y:"mwaka mmoja",yy:"miaka %d"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),{1:"௧",2:"௨",3:"௩",4:"௪",5:"௫",6:"௬",7:"௭",8:"௮",9:"௯",0:"௦"}),db={"௧":"1","௨":"2","௩":"3","௪":"4","௫":"5","௬":"6","௭":"7","௮":"8","௯":"9","௦":"0"},eb=(a.defineLocale("ta",{months:"ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்".split("_"),monthsShort:"ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்".split("_"),weekdays:"ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை".split("_"),weekdaysShort:"ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி".split("_"),weekdaysMin:"ஞா_தி_செ_பு_வி_வெ_ச".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, HH:mm",LLLL:"dddd, D MMMM YYYY, HH:mm"},calendar:{sameDay:"[இன்று] LT",nextDay:"[நாளை] LT",nextWeek:"dddd, LT",lastDay:"[நேற்று] LT",lastWeek:"[கடந்த வாரம்] dddd, LT",sameElse:"L"},relativeTime:{future:"%s இல்",past:"%s முன்",s:"ஒரு சில விநாடிகள்",m:"ஒரு நிமிடம்",mm:"%d நிமிடங்கள்",h:"ஒரு மணி நேரம்",hh:"%d மணி நேரம்",d:"ஒரு நாள்",dd:"%d நாட்கள்",M:"ஒரு மாதம்",MM:"%d மாதங்கள்",y:"ஒரு வருடம்",yy:"%d ஆண்டுகள்"},ordinalParse:/\d{1,2}வது/,ordinal:function(a){return a+"வது"},preparse:function(a){return a.replace(/[௧௨௩௪௫௬௭௮௯௦]/g,function(a){return db[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return cb[a]})}, +// refer http://ta.wikipedia.org/s/1er1 +meridiemParse:/யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/,meridiem:function(a,b,c){return 2>a?" யாமம்":6>a?" வைகறை":10>a?" காலை":14>a?" நண்பகல்":18>a?" எற்பாடு":22>a?" மாலை":" யாமம்"},meridiemHour:function(a,b){return 12===a&&(a=0),"யாமம்"===b?2>a?a:a+12:"வைகறை"===b||"காலை"===b?a:"நண்பகல்"===b&&a>=10?a:a+12},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),a.defineLocale("te",{months:"జనవరి_ఫిబ్రవరి_మార్చి_ఏప్రిల్_మే_జూన్_జూలై_ఆగస్టు_సెప్టెంబర్_అక్టోబర్_నవంబర్_డిసెంబర్".split("_"),monthsShort:"జన._ఫిబ్ర._మార్చి_ఏప్రి._మే_జూన్_జూలై_ఆగ._సెప్._అక్టో._నవ._డిసె.".split("_"),monthsParseExact:!0,weekdays:"ఆదివారం_సోమవారం_మంగళవారం_బుధవారం_గురువారం_శుక్రవారం_శనివారం".split("_"),weekdaysShort:"ఆది_సోమ_మంగళ_బుధ_గురు_శుక్ర_శని".split("_"),weekdaysMin:"ఆ_సో_మం_బు_గు_శు_శ".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[నేడు] LT",nextDay:"[రేపు] LT",nextWeek:"dddd, LT",lastDay:"[నిన్న] LT",lastWeek:"[గత] dddd, LT",sameElse:"L"},relativeTime:{future:"%s లో",past:"%s క్రితం",s:"కొన్ని క్షణాలు",m:"ఒక నిమిషం",mm:"%d నిమిషాలు",h:"ఒక గంట",hh:"%d గంటలు",d:"ఒక రోజు",dd:"%d రోజులు",M:"ఒక నెల",MM:"%d నెలలు",y:"ఒక సంవత్సరం",yy:"%d సంవత్సరాలు"},ordinalParse:/\d{1,2}వ/,ordinal:"%dవ",meridiemParse:/రాత్రి|ఉదయం|మధ్యాహ్నం|సాయంత్రం/,meridiemHour:function(a,b){return 12===a&&(a=0),"రాత్రి"===b?4>a?a:a+12:"ఉదయం"===b?a:"మధ్యాహ్నం"===b?a>=10?a:a+12:"సాయంత్రం"===b?a+12:void 0},meridiem:function(a,b,c){return 4>a?"రాత్రి":10>a?"ఉదయం":17>a?"మధ్యాహ్నం":20>a?"సాయంత్రం":"రాత్రి"},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),a.defineLocale("th",{months:"มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"),monthsShort:"ม.ค._ก.พ._มี.ค._เม.ย._พ.ค._มิ.ย._ก.ค._ส.ค._ก.ย._ต.ค._พ.ย._ธ.ค.".split("_"),monthsParseExact:!0,weekdays:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"),weekdaysShort:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"),// yes, three characters difference +weekdaysMin:"อา._จ._อ._พ._พฤ._ศ._ส.".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H นาฬิกา m นาที",LTS:"H นาฬิกา m นาที s วินาที",L:"YYYY/MM/DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY เวลา H นาฬิกา m นาที",LLLL:"วันddddที่ D MMMM YYYY เวลา H นาฬิกา m นาที"},meridiemParse:/ก่อนเที่ยง|หลังเที่ยง/,isPM:function(a){return"หลังเที่ยง"===a},meridiem:function(a,b,c){return 12>a?"ก่อนเที่ยง":"หลังเที่ยง"},calendar:{sameDay:"[วันนี้ เวลา] LT",nextDay:"[พรุ่งนี้ เวลา] LT",nextWeek:"dddd[หน้า เวลา] LT",lastDay:"[เมื่อวานนี้ เวลา] LT",lastWeek:"[วัน]dddd[ที่แล้ว เวลา] LT",sameElse:"L"},relativeTime:{future:"อีก %s",past:"%sที่แล้ว",s:"ไม่กี่วินาที",m:"1 นาที",mm:"%d นาที",h:"1 ชั่วโมง",hh:"%d ชั่วโมง",d:"1 วัน",dd:"%d วัน",M:"1 เดือน",MM:"%d เดือน",y:"1 ปี",yy:"%d ปี"}}),a.defineLocale("tl-ph",{months:"Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre".split("_"),monthsShort:"Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis".split("_"),weekdays:"Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado".split("_"),weekdaysShort:"Lin_Lun_Mar_Miy_Huw_Biy_Sab".split("_"),weekdaysMin:"Li_Lu_Ma_Mi_Hu_Bi_Sab".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"MM/D/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY HH:mm",LLLL:"dddd, MMMM DD, YYYY HH:mm"},calendar:{sameDay:"[Ngayon sa] LT",nextDay:"[Bukas sa] LT",nextWeek:"dddd [sa] LT",lastDay:"[Kahapon sa] LT",lastWeek:"dddd [huling linggo] LT",sameElse:"L"},relativeTime:{future:"sa loob ng %s",past:"%s ang nakalipas",s:"ilang segundo",m:"isang minuto",mm:"%d minuto",h:"isang oras",hh:"%d oras",d:"isang araw",dd:"%d araw",M:"isang buwan",MM:"%d buwan",y:"isang taon",yy:"%d taon"},ordinalParse:/\d{1,2}/,ordinal:function(a){return a},week:{dow:1,// Monday is the first day of the week. +doy:4}}),"pagh_wa’_cha’_wej_loS_vagh_jav_Soch_chorgh_Hut".split("_")),fb=(a.defineLocale("tlh",{months:"tera’ jar wa’_tera’ jar cha’_tera’ jar wej_tera’ jar loS_tera’ jar vagh_tera’ jar jav_tera’ jar Soch_tera’ jar chorgh_tera’ jar Hut_tera’ jar wa’maH_tera’ jar wa’maH wa’_tera’ jar wa’maH cha’".split("_"),monthsShort:"jar wa’_jar cha’_jar wej_jar loS_jar vagh_jar jav_jar Soch_jar chorgh_jar Hut_jar wa’maH_jar wa’maH wa’_jar wa’maH cha’".split("_"),monthsParseExact:!0,weekdays:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),weekdaysShort:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),weekdaysMin:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[DaHjaj] LT",nextDay:"[wa’leS] LT",nextWeek:"LLL",lastDay:"[wa’Hu’] LT",lastWeek:"LLL",sameElse:"L"},relativeTime:{future:S,past:T,s:"puS lup",m:"wa’ tup",mm:U,h:"wa’ rep",hh:U,d:"wa’ jaj",dd:U,M:"wa’ jar",MM:U,y:"wa’ DIS",yy:U},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),{1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'üncü",4:"'üncü",100:"'üncü",6:"'ncı",9:"'uncu",10:"'uncu",30:"'uncu",60:"'ıncı",90:"'ıncı"});a.defineLocale("tr",{months:"Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"),monthsShort:"Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"),weekdaysMin:"Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[yarın saat] LT",nextWeek:"[haftaya] dddd [saat] LT",lastDay:"[dün] LT",lastWeek:"[geçen hafta] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s önce",s:"birkaç saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir yıl",yy:"%d yıl"},ordinalParse:/\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,ordinal:function(a){if(0===a)// special case for zero +return a+"'ıncı";var b=a%10,c=a%100-b,d=a>=100?100:null;return a+(fb[b]||fb[c]||fb[d])},week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("tzl",{months:"Januar_Fevraglh_Març_Avrïu_Mai_Gün_Julia_Guscht_Setemvar_Listopäts_Noemvar_Zecemvar".split("_"),monthsShort:"Jan_Fev_Mar_Avr_Mai_Gün_Jul_Gus_Set_Lis_Noe_Zec".split("_"),weekdays:"Súladi_Lúneçi_Maitzi_Márcuri_Xhúadi_Viénerçi_Sáturi".split("_"),weekdaysShort:"Súl_Lún_Mai_Már_Xhú_Vié_Sát".split("_"),weekdaysMin:"Sú_Lú_Ma_Má_Xh_Vi_Sá".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"D. MMMM [dallas] YYYY",LLL:"D. MMMM [dallas] YYYY HH.mm",LLLL:"dddd, [li] D. MMMM [dallas] YYYY HH.mm"},meridiemParse:/d\'o|d\'a/i,isPM:function(a){return"d'o"===a.toLowerCase()},meridiem:function(a,b,c){return a>11?c?"d'o":"D'O":c?"d'a":"D'A"},calendar:{sameDay:"[oxhi à] LT",nextDay:"[demà à] LT",nextWeek:"dddd [à] LT",lastDay:"[ieiri à] LT",lastWeek:"[sür el] dddd [lasteu à] LT",sameElse:"L"},relativeTime:{future:"osprei %s",past:"ja%s",s:W,m:W,mm:W,h:W,hh:W,d:W,dd:W,M:W,MM:W,y:W,yy:W},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("tzm-latn",{months:"innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),monthsShort:"innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),weekdays:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),weekdaysShort:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),weekdaysMin:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[asdkh g] LT",nextDay:"[aska g] LT",nextWeek:"dddd [g] LT",lastDay:"[assant g] LT",lastWeek:"dddd [g] LT",sameElse:"L"},relativeTime:{future:"dadkh s yan %s",past:"yan %s",s:"imik",m:"minuḍ",mm:"%d minuḍ",h:"saɛa",hh:"%d tassaɛin",d:"ass",dd:"%d ossan",M:"ayowr",MM:"%d iyyirn",y:"asgas",yy:"%d isgasn"},week:{dow:6,// Saturday is the first day of the week. +doy:12}}),a.defineLocale("tzm",{months:"ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),monthsShort:"ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),weekdays:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),weekdaysShort:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),weekdaysMin:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[ⴰⵙⴷⵅ ⴴ] LT",nextDay:"[ⴰⵙⴽⴰ ⴴ] LT",nextWeek:"dddd [ⴴ] LT",lastDay:"[ⴰⵚⴰⵏⵜ ⴴ] LT",lastWeek:"dddd [ⴴ] LT",sameElse:"L"},relativeTime:{future:"ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s",past:"ⵢⴰⵏ %s",s:"ⵉⵎⵉⴽ",m:"ⵎⵉⵏⵓⴺ",mm:"%d ⵎⵉⵏⵓⴺ",h:"ⵙⴰⵄⴰ",hh:"%d ⵜⴰⵙⵙⴰⵄⵉⵏ",d:"ⴰⵙⵙ",dd:"%d oⵙⵙⴰⵏ",M:"ⴰⵢoⵓⵔ",MM:"%d ⵉⵢⵢⵉⵔⵏ",y:"ⴰⵙⴳⴰⵙ",yy:"%d ⵉⵙⴳⴰⵙⵏ"},week:{dow:6,// Saturday is the first day of the week. +doy:12}}),a.defineLocale("uk",{months:{format:"січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня".split("_"),standalone:"січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень".split("_")},monthsShort:"січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),weekdays:Z,weekdaysShort:"нд_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY р.",LLL:"D MMMM YYYY р., HH:mm",LLLL:"dddd, D MMMM YYYY р., HH:mm"},calendar:{sameDay:$("[Сьогодні "),nextDay:$("[Завтра "),lastDay:$("[Вчора "),nextWeek:$("[У] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return $("[Минулої] dddd [").call(this);case 1:case 2:case 4:return $("[Минулого] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"за %s",past:"%s тому",s:"декілька секунд",m:Y,mm:Y,h:"годину",hh:Y,d:"день",dd:Y,M:"місяць",MM:Y,y:"рік",yy:Y}, +// M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason +meridiemParse:/ночі|ранку|дня|вечора/,isPM:function(a){return/^(дня|вечора)$/.test(a)},meridiem:function(a,b,c){return 4>a?"ночі":12>a?"ранку":17>a?"дня":"вечора"},ordinalParse:/\d{1,2}-(й|го)/,ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":case"w":case"W":return a+"-й";case"D":return a+"-го";default:return a}},week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("uz",{months:"январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр".split("_"),monthsShort:"янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек".split("_"),weekdays:"Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба".split("_"),weekdaysShort:"Якш_Душ_Сеш_Чор_Пай_Жум_Шан".split("_"),weekdaysMin:"Як_Ду_Се_Чо_Па_Жу_Ша".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"D MMMM YYYY, dddd HH:mm"},calendar:{sameDay:"[Бугун соат] LT [да]",nextDay:"[Эртага] LT [да]",nextWeek:"dddd [куни соат] LT [да]",lastDay:"[Кеча соат] LT [да]",lastWeek:"[Утган] dddd [куни соат] LT [да]",sameElse:"L"},relativeTime:{future:"Якин %s ичида",past:"Бир неча %s олдин",s:"фурсат",m:"бир дакика",mm:"%d дакика",h:"бир соат",hh:"%d соат",d:"бир кун",dd:"%d кун",M:"бир ой",MM:"%d ой",y:"бир йил",yy:"%d йил"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),a.defineLocale("vi",{months:"tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12".split("_"),monthsShort:"Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12".split("_"),monthsParseExact:!0,weekdays:"chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy".split("_"),weekdaysShort:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysMin:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysParseExact:!0,meridiemParse:/sa|ch/i,isPM:function(a){return/^ch$/i.test(a)},meridiem:function(a,b,c){return 12>a?c?"sa":"SA":c?"ch":"CH"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [năm] YYYY",LLL:"D MMMM [năm] YYYY HH:mm",LLLL:"dddd, D MMMM [năm] YYYY HH:mm",l:"DD/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[Hôm nay lúc] LT",nextDay:"[Ngày mai lúc] LT",nextWeek:"dddd [tuần tới lúc] LT",lastDay:"[Hôm qua lúc] LT",lastWeek:"dddd [tuần rồi lúc] LT",sameElse:"L"},relativeTime:{future:"%s tới",past:"%s trước",s:"vài giây",m:"một phút",mm:"%d phút",h:"một giờ",hh:"%d giờ",d:"một ngày",dd:"%d ngày",M:"một tháng",MM:"%d tháng",y:"một năm",yy:"%d năm"},ordinalParse:/\d{1,2}/,ordinal:function(a){return a},week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("x-pseudo",{months:"J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér".split("_"),monthsShort:"J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc".split("_"),monthsParseExact:!0,weekdays:"S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý".split("_"),weekdaysShort:"S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát".split("_"),weekdaysMin:"S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[T~ódá~ý át] LT",nextDay:"[T~ómó~rró~w át] LT",nextWeek:"dddd [át] LT",lastDay:"[Ý~ést~érdá~ý át] LT",lastWeek:"[L~ást] dddd [át] LT",sameElse:"L"},relativeTime:{future:"í~ñ %s",past:"%s á~gó",s:"á ~féw ~sécó~ñds",m:"á ~míñ~úté",mm:"%d m~íñú~tés",h:"á~ñ hó~úr",hh:"%d h~óúrs",d:"á ~dáý",dd:"%d d~áýs",M:"á ~móñ~th",MM:"%d m~óñt~hs",y:"á ~ýéár",yy:"%d ý~éárs"},ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("zh-cn",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah点mm分",LTS:"Ah点m分s秒",L:"YYYY-MM-DD",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日Ah点mm分",LLLL:"YYYY年MMMD日ddddAh点mm分",l:"YYYY-MM-DD",ll:"YYYY年MMMD日",lll:"YYYY年MMMD日Ah点mm分",llll:"YYYY年MMMD日ddddAh点mm分"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(a,b){return 12===a&&(a=0),"凌晨"===b||"早上"===b||"上午"===b?a:"下午"===b||"晚上"===b?a+12:a>=11?a:a+12},meridiem:function(a,b,c){var d=100*a+b;return 600>d?"凌晨":900>d?"早上":1130>d?"上午":1230>d?"中午":1800>d?"下午":"晚上"},calendar:{sameDay:function(){return 0===this.minutes()?"[今天]Ah[点整]":"[今天]LT"},nextDay:function(){return 0===this.minutes()?"[明天]Ah[点整]":"[明天]LT"},lastDay:function(){return 0===this.minutes()?"[昨天]Ah[点整]":"[昨天]LT"},nextWeek:function(){var b,c;return b=a().startOf("week"),c=this.diff(b,"days")>=7?"[下]":"[本]",0===this.minutes()?c+"dddAh点整":c+"dddAh点mm"},lastWeek:function(){var b,c;return b=a().startOf("week"),c=this.unix()<b.unix()?"[上]":"[本]",0===this.minutes()?c+"dddAh点整":c+"dddAh点mm"},sameElse:"LL"},ordinalParse:/\d{1,2}(日|月|周)/,ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"日";case"M":return a+"月";case"w":case"W":return a+"周";default:return a}},relativeTime:{future:"%s内",past:"%s前",s:"几秒",m:"1 分钟",mm:"%d 分钟",h:"1 小时",hh:"%d 小时",d:"1 天",dd:"%d 天",M:"1 个月",MM:"%d 个月",y:"1 年",yy:"%d 年"},week:{ +// GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效 +dow:1,// Monday is the first day of the week. +doy:4}}),a.defineLocale("zh-tw",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah點mm分",LTS:"Ah點m分s秒",L:"YYYY年MMMD日",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日Ah點mm分",LLLL:"YYYY年MMMD日ddddAh點mm分",l:"YYYY年MMMD日",ll:"YYYY年MMMD日",lll:"YYYY年MMMD日Ah點mm分",llll:"YYYY年MMMD日ddddAh點mm分"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(a,b){return 12===a&&(a=0),"凌晨"===b||"早上"===b||"上午"===b?a:"中午"===b?a>=11?a:a+12:"下午"===b||"晚上"===b?a+12:void 0},meridiem:function(a,b,c){var d=100*a+b;return 600>d?"凌晨":900>d?"早上":1130>d?"上午":1230>d?"中午":1800>d?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},ordinalParse:/\d{1,2}(日|月|週)/,ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"日";case"M":return a+"月";case"w":case"W":return a+"週";default:return a}},relativeTime:{future:"%s內",past:"%s前",s:"幾秒",m:"1 分鐘",mm:"%d 分鐘",h:"1 小時",hh:"%d 小時",d:"1 天",dd:"%d 天",M:"1 個月",MM:"%d 個月",y:"1 年",yy:"%d 年"}});a.locale("en")});
@@ -0,0 +1,11954 @@
+//! moment.js +//! version : 2.14.1 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + global.moment = factory() +}(this, function () { 'use strict'; + + var hookCallback; + + function utils_hooks__hooks () { + return hookCallback.apply(null, arguments); + } + + // This is done to register the method called with moment() + // without creating circular dependencies. + function setHookCallback (callback) { + hookCallback = callback; + } + + function isArray(input) { + return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]'; + } + + function isObject(input) { + return Object.prototype.toString.call(input) === '[object Object]'; + } + + function isObjectEmpty(obj) { + var k; + for (k in obj) { + // even if its not own property I'd still call it non-empty + return false; + } + return true; + } + + function isDate(input) { + return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]'; + } + + function map(arr, fn) { + var res = [], i; + for (i = 0; i < arr.length; ++i) { + res.push(fn(arr[i], i)); + } + return res; + } + + function hasOwnProp(a, b) { + return Object.prototype.hasOwnProperty.call(a, b); + } + + function extend(a, b) { + for (var i in b) { + if (hasOwnProp(b, i)) { + a[i] = b[i]; + } + } + + if (hasOwnProp(b, 'toString')) { + a.toString = b.toString; + } + + if (hasOwnProp(b, 'valueOf')) { + a.valueOf = b.valueOf; + } + + return a; + } + + function create_utc__createUTC (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, true).utc(); + } + + function defaultParsingFlags() { + // We need to deep clone this object. + return { + empty : false, + unusedTokens : [], + unusedInput : [], + overflow : -2, + charsLeftOver : 0, + nullInput : false, + invalidMonth : null, + invalidFormat : false, + userInvalidated : false, + iso : false, + parsedDateParts : [], + meridiem : null + }; + } + + function getParsingFlags(m) { + if (m._pf == null) { + m._pf = defaultParsingFlags(); + } + return m._pf; + } + + var some; + if (Array.prototype.some) { + some = Array.prototype.some; + } else { + some = function (fun) { + var t = Object(this); + var len = t.length >>> 0; + + for (var i = 0; i < len; i++) { + if (i in t && fun.call(this, t[i], i, t)) { + return true; + } + } + + return false; + }; + } + + function valid__isValid(m) { + if (m._isValid == null) { + var flags = getParsingFlags(m); + var parsedParts = some.call(flags.parsedDateParts, function (i) { + return i != null; + }); + m._isValid = !isNaN(m._d.getTime()) && + flags.overflow < 0 && + !flags.empty && + !flags.invalidMonth && + !flags.invalidWeekday && + !flags.nullInput && + !flags.invalidFormat && + !flags.userInvalidated && + (!flags.meridiem || (flags.meridiem && parsedParts)); + + if (m._strict) { + m._isValid = m._isValid && + flags.charsLeftOver === 0 && + flags.unusedTokens.length === 0 && + flags.bigHour === undefined; + } + } + return m._isValid; + } + + function valid__createInvalid (flags) { + var m = create_utc__createUTC(NaN); + if (flags != null) { + extend(getParsingFlags(m), flags); + } + else { + getParsingFlags(m).userInvalidated = true; + } + + return m; + } + + function isUndefined(input) { + return input === void 0; + } + + // Plugins that add properties should also add the key here (null value), + // so we can properly clone ourselves. + var momentProperties = utils_hooks__hooks.momentProperties = []; + + function copyConfig(to, from) { + var i, prop, val; + + if (!isUndefined(from._isAMomentObject)) { + to._isAMomentObject = from._isAMomentObject; + } + if (!isUndefined(from._i)) { + to._i = from._i; + } + if (!isUndefined(from._f)) { + to._f = from._f; + } + if (!isUndefined(from._l)) { + to._l = from._l; + } + if (!isUndefined(from._strict)) { + to._strict = from._strict; + } + if (!isUndefined(from._tzm)) { + to._tzm = from._tzm; + } + if (!isUndefined(from._isUTC)) { + to._isUTC = from._isUTC; + } + if (!isUndefined(from._offset)) { + to._offset = from._offset; + } + if (!isUndefined(from._pf)) { + to._pf = getParsingFlags(from); + } + if (!isUndefined(from._locale)) { + to._locale = from._locale; + } + + if (momentProperties.length > 0) { + for (i in momentProperties) { + prop = momentProperties[i]; + val = from[prop]; + if (!isUndefined(val)) { + to[prop] = val; + } + } + } + + return to; + } + + var updateInProgress = false; + + // Moment prototype object + function Moment(config) { + copyConfig(this, config); + this._d = new Date(config._d != null ? config._d.getTime() : NaN); + // Prevent infinite loop in case updateOffset creates new moment + // objects. + if (updateInProgress === false) { + updateInProgress = true; + utils_hooks__hooks.updateOffset(this); + updateInProgress = false; + } + } + + function isMoment (obj) { + return obj instanceof Moment || (obj != null && obj._isAMomentObject != null); + } + + function absFloor (number) { + if (number < 0) { + // -0 -> 0 + return Math.ceil(number) || 0; + } else { + return Math.floor(number); + } + } + + function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; + + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + value = absFloor(coercedNumber); + } + + return value; + } + + // compare two arrays, return the number of differences + function compareArrays(array1, array2, dontConvert) { + var len = Math.min(array1.length, array2.length), + lengthDiff = Math.abs(array1.length - array2.length), + diffs = 0, + i; + for (i = 0; i < len; i++) { + if ((dontConvert && array1[i] !== array2[i]) || + (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { + diffs++; + } + } + return diffs + lengthDiff; + } + + function warn(msg) { + if (utils_hooks__hooks.suppressDeprecationWarnings === false && + (typeof console !== 'undefined') && console.warn) { + console.warn('Deprecation warning: ' + msg); + } + } + + function deprecate(msg, fn) { + var firstTime = true; + + return extend(function () { + if (utils_hooks__hooks.deprecationHandler != null) { + utils_hooks__hooks.deprecationHandler(null, msg); + } + if (firstTime) { + warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack); + firstTime = false; + } + return fn.apply(this, arguments); + }, fn); + } + + var deprecations = {}; + + function deprecateSimple(name, msg) { + if (utils_hooks__hooks.deprecationHandler != null) { + utils_hooks__hooks.deprecationHandler(name, msg); + } + if (!deprecations[name]) { + warn(msg); + deprecations[name] = true; + } + } + + utils_hooks__hooks.suppressDeprecationWarnings = false; + utils_hooks__hooks.deprecationHandler = null; + + function isFunction(input) { + return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]'; + } + + function locale_set__set (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (isFunction(prop)) { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + this._config = config; + // Lenient ordinal parsing accepts just a number in addition to + // number + (possibly) stuff coming from _ordinalParseLenient. + this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source); + } + + function mergeConfigs(parentConfig, childConfig) { + var res = extend({}, parentConfig), prop; + for (prop in childConfig) { + if (hasOwnProp(childConfig, prop)) { + if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) { + res[prop] = {}; + extend(res[prop], parentConfig[prop]); + extend(res[prop], childConfig[prop]); + } else if (childConfig[prop] != null) { + res[prop] = childConfig[prop]; + } else { + delete res[prop]; + } + } + } + for (prop in parentConfig) { + if (hasOwnProp(parentConfig, prop) && + !hasOwnProp(childConfig, prop) && + isObject(parentConfig[prop])) { + // make sure changes to properties don't modify parent config + res[prop] = extend({}, res[prop]); + } + } + return res; + } + + function Locale(config) { + if (config != null) { + this.set(config); + } + } + + var keys; + + if (Object.keys) { + keys = Object.keys; + } else { + keys = function (obj) { + var i, res = []; + for (i in obj) { + if (hasOwnProp(obj, i)) { + res.push(i); + } + } + return res; + }; + } + + var defaultCalendar = { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }; + + function locale_calendar__calendar (key, mom, now) { + var output = this._calendar[key] || this._calendar['sameElse']; + return isFunction(output) ? output.call(mom, now) : output; + } + + var defaultLongDateFormat = { + LTS : 'h:mm:ss A', + LT : 'h:mm A', + L : 'MM/DD/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY h:mm A', + LLLL : 'dddd, MMMM D, YYYY h:mm A' + }; + + function longDateFormat (key) { + var format = this._longDateFormat[key], + formatUpper = this._longDateFormat[key.toUpperCase()]; + + if (format || !formatUpper) { + return format; + } + + this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) { + return val.slice(1); + }); + + return this._longDateFormat[key]; + } + + var defaultInvalidDate = 'Invalid date'; + + function invalidDate () { + return this._invalidDate; + } + + var defaultOrdinal = '%d'; + var defaultOrdinalParse = /\d{1,2}/; + + function ordinal (number) { + return this._ordinal.replace('%d', number); + } + + var defaultRelativeTime = { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }; + + function relative__relativeTime (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (isFunction(output)) ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); + } + + function pastFuture (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return isFunction(format) ? format(output) : format.replace(/%s/i, output); + } + + var aliases = {}; + + function addUnitAlias (unit, shorthand) { + var lowerCase = unit.toLowerCase(); + aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit; + } + + function normalizeUnits(units) { + return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined; + } + + function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; + + for (prop in inputObject) { + if (hasOwnProp(inputObject, prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } + + return normalizedInput; + } + + var priorities = {}; + + function addUnitPriority(unit, priority) { + priorities[unit] = priority; + } + + function getPrioritizedUnits(unitsObj) { + var units = []; + for (var u in unitsObj) { + units.push({unit: u, priority: priorities[u]}); + } + units.sort(function (a, b) { + return a.priority - b.priority; + }); + return units; + } + + function makeGetSet (unit, keepTime) { + return function (value) { + if (value != null) { + get_set__set(this, unit, value); + utils_hooks__hooks.updateOffset(this, keepTime); + return this; + } else { + return get_set__get(this, unit); + } + }; + } + + function get_set__get (mom, unit) { + return mom.isValid() ? + mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN; + } + + function get_set__set (mom, unit, value) { + if (mom.isValid()) { + mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); + } + } + + // MOMENTS + + function stringGet (units) { + units = normalizeUnits(units); + if (isFunction(this[units])) { + return this[units](); + } + return this; + } + + + function stringSet (units, value) { + if (typeof units === 'object') { + units = normalizeObjectUnits(units); + var prioritized = getPrioritizedUnits(units); + for (var i = 0; i < prioritized.length; i++) { + this[prioritized[i].unit](units[prioritized[i].unit]); + } + } else { + units = normalizeUnits(units); + if (isFunction(this[units])) { + return this[units](value); + } + } + return this; + } + + function zeroFill(number, targetLength, forceSign) { + var absNumber = '' + Math.abs(number), + zerosToFill = targetLength - absNumber.length, + sign = number >= 0; + return (sign ? (forceSign ? '+' : '') : '-') + + Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber; + } + + var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g; + + var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g; + + var formatFunctions = {}; + + var formatTokenFunctions = {}; + + // token: 'M' + // padded: ['MM', 2] + // ordinal: 'Mo' + // callback: function () { this.month() + 1 } + function addFormatToken (token, padded, ordinal, callback) { + var func = callback; + if (typeof callback === 'string') { + func = function () { + return this[callback](); + }; + } + if (token) { + formatTokenFunctions[token] = func; + } + if (padded) { + formatTokenFunctions[padded[0]] = function () { + return zeroFill(func.apply(this, arguments), padded[1], padded[2]); + }; + } + if (ordinal) { + formatTokenFunctions[ordinal] = function () { + return this.localeData().ordinal(func.apply(this, arguments), token); + }; + } + } + + function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + return input.replace(/^\[|\]$/g, ''); + } + return input.replace(/\\/g, ''); + } + + function makeFormatFunction(format) { + var array = format.match(formattingTokens), i, length; + + for (i = 0, length = array.length; i < length; i++) { + if (formatTokenFunctions[array[i]]) { + array[i] = formatTokenFunctions[array[i]]; + } else { + array[i] = removeFormattingTokens(array[i]); + } + } + + return function (mom) { + var output = '', i; + for (i = 0; i < length; i++) { + output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; + } + return output; + }; + } + + // format date using native date object + function formatMoment(m, format) { + if (!m.isValid()) { + return m.localeData().invalidDate(); + } + + format = expandFormat(format, m.localeData()); + formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format); + + return formatFunctions[format](m); + } + + function expandFormat(format, locale) { + var i = 5; + + function replaceLongDateFormatTokens(input) { + return locale.longDateFormat(input) || input; + } + + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } + + return format; + } + + var match1 = /\d/; // 0 - 9 + var match2 = /\d\d/; // 00 - 99 + var match3 = /\d{3}/; // 000 - 999 + var match4 = /\d{4}/; // 0000 - 9999 + var match6 = /[+-]?\d{6}/; // -999999 - 999999 + var match1to2 = /\d\d?/; // 0 - 99 + var match3to4 = /\d\d\d\d?/; // 999 - 9999 + var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999 + var match1to3 = /\d{1,3}/; // 0 - 999 + var match1to4 = /\d{1,4}/; // 0 - 9999 + var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999 + + var matchUnsigned = /\d+/; // 0 - inf + var matchSigned = /[+-]?\d+/; // -inf - inf + + var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z + var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z + + var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123 + + // any word (or two) characters or numbers including two/three word month in arabic. + // includes scottish gaelic two word and hyphenated months + var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i; + + + var regexes = {}; + + function addRegexToken (token, regex, strictRegex) { + regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) { + return (isStrict && strictRegex) ? strictRegex : regex; + }; + } + + function getParseRegexForToken (token, config) { + if (!hasOwnProp(regexes, token)) { + return new RegExp(unescapeFormat(token)); + } + + return regexes[token](config._strict, config._locale); + } + + // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript + function unescapeFormat(s) { + return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + })); + } + + function regexEscape(s) { + return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + } + + var tokens = {}; + + function addParseToken (token, callback) { + var i, func = callback; + if (typeof token === 'string') { + token = [token]; + } + if (typeof callback === 'number') { + func = function (input, array) { + array[callback] = toInt(input); + }; + } + for (i = 0; i < token.length; i++) { + tokens[token[i]] = func; + } + } + + function addWeekParseToken (token, callback) { + addParseToken(token, function (input, array, config, token) { + config._w = config._w || {}; + callback(input, config._w, config, token); + }); + } + + function addTimeToArrayFromToken(token, input, config) { + if (input != null && hasOwnProp(tokens, token)) { + tokens[token](input, config._a, config, token); + } + } + + var YEAR = 0; + var MONTH = 1; + var DATE = 2; + var HOUR = 3; + var MINUTE = 4; + var SECOND = 5; + var MILLISECOND = 6; + var WEEK = 7; + var WEEKDAY = 8; + + var indexOf; + + if (Array.prototype.indexOf) { + indexOf = Array.prototype.indexOf; + } else { + indexOf = function (o) { + // I know + var i; + for (i = 0; i < this.length; ++i) { + if (this[i] === o) { + return i; + } + } + return -1; + }; + } + + function daysInMonth(year, month) { + return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); + } + + // FORMATTING + + addFormatToken('M', ['MM', 2], 'Mo', function () { + return this.month() + 1; + }); + + addFormatToken('MMM', 0, 0, function (format) { + return this.localeData().monthsShort(this, format); + }); + + addFormatToken('MMMM', 0, 0, function (format) { + return this.localeData().months(this, format); + }); + + // ALIASES + + addUnitAlias('month', 'M'); + + // PRIORITY + + addUnitPriority('month', 8); + + // PARSING + + addRegexToken('M', match1to2); + addRegexToken('MM', match1to2, match2); + addRegexToken('MMM', function (isStrict, locale) { + return locale.monthsShortRegex(isStrict); + }); + addRegexToken('MMMM', function (isStrict, locale) { + return locale.monthsRegex(isStrict); + }); + + addParseToken(['M', 'MM'], function (input, array) { + array[MONTH] = toInt(input) - 1; + }); + + addParseToken(['MMM', 'MMMM'], function (input, array, config, token) { + var month = config._locale.monthsParse(input, token, config._strict); + // if we didn't find a month name, mark the date as invalid. + if (month != null) { + array[MONTH] = month; + } else { + getParsingFlags(config).invalidMonth = input; + } + }); + + // LOCALES + + var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/; + var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'); + function localeMonths (m, format) { + return isArray(this._months) ? this._months[m.month()] : + this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()]; + } + + var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'); + function localeMonthsShort (m, format) { + return isArray(this._monthsShort) ? this._monthsShort[m.month()] : + this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()]; + } + + function units_month__handleStrictParse(monthName, format, strict) { + var i, ii, mom, llc = monthName.toLocaleLowerCase(); + if (!this._monthsParse) { + // this is not used + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + for (i = 0; i < 12; ++i) { + mom = create_utc__createUTC([2000, i]); + this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase(); + this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase(); + } + } + + if (strict) { + if (format === 'MMM') { + ii = indexOf.call(this._shortMonthsParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._longMonthsParse, llc); + return ii !== -1 ? ii : null; + } + } else { + if (format === 'MMM') { + ii = indexOf.call(this._shortMonthsParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._longMonthsParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._longMonthsParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortMonthsParse, llc); + return ii !== -1 ? ii : null; + } + } + } + + function localeMonthsParse (monthName, format, strict) { + var i, mom, regex; + + if (this._monthsParseExact) { + return units_month__handleStrictParse.call(this, monthName, format, strict); + } + + if (!this._monthsParse) { + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + } + + // TODO: add sorting + // Sorting makes sure if one month (or abbr) is a prefix of another + // see sorting in computeMonthsParse + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = create_utc__createUTC([2000, i]); + if (strict && !this._longMonthsParse[i]) { + this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i'); + this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i'); + } + if (!strict && !this._monthsParse[i]) { + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) { + return i; + } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) { + return i; + } else if (!strict && this._monthsParse[i].test(monthName)) { + return i; + } + } + } + + // MOMENTS + + function setMonth (mom, value) { + var dayOfMonth; + + if (!mom.isValid()) { + // No op + return mom; + } + + if (typeof value === 'string') { + if (/^\d+$/.test(value)) { + value = toInt(value); + } else { + value = mom.localeData().monthsParse(value); + // TODO: Another silent failure? + if (typeof value !== 'number') { + return mom; + } + } + } + + dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value)); + mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); + return mom; + } + + function getSetMonth (value) { + if (value != null) { + setMonth(this, value); + utils_hooks__hooks.updateOffset(this, true); + return this; + } else { + return get_set__get(this, 'Month'); + } + } + + function getDaysInMonth () { + return daysInMonth(this.year(), this.month()); + } + + var defaultMonthsShortRegex = matchWord; + function monthsShortRegex (isStrict) { + if (this._monthsParseExact) { + if (!hasOwnProp(this, '_monthsRegex')) { + computeMonthsParse.call(this); + } + if (isStrict) { + return this._monthsShortStrictRegex; + } else { + return this._monthsShortRegex; + } + } else { + if (!hasOwnProp(this, '_monthsShortRegex')) { + this._monthsShortRegex = defaultMonthsShortRegex; + } + return this._monthsShortStrictRegex && isStrict ? + this._monthsShortStrictRegex : this._monthsShortRegex; + } + } + + var defaultMonthsRegex = matchWord; + function monthsRegex (isStrict) { + if (this._monthsParseExact) { + if (!hasOwnProp(this, '_monthsRegex')) { + computeMonthsParse.call(this); + } + if (isStrict) { + return this._monthsStrictRegex; + } else { + return this._monthsRegex; + } + } else { + if (!hasOwnProp(this, '_monthsRegex')) { + this._monthsRegex = defaultMonthsRegex; + } + return this._monthsStrictRegex && isStrict ? + this._monthsStrictRegex : this._monthsRegex; + } + } + + function computeMonthsParse () { + function cmpLenRev(a, b) { + return b.length - a.length; + } + + var shortPieces = [], longPieces = [], mixedPieces = [], + i, mom; + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = create_utc__createUTC([2000, i]); + shortPieces.push(this.monthsShort(mom, '')); + longPieces.push(this.months(mom, '')); + mixedPieces.push(this.months(mom, '')); + mixedPieces.push(this.monthsShort(mom, '')); + } + // Sorting makes sure if one month (or abbr) is a prefix of another it + // will match the longer piece. + shortPieces.sort(cmpLenRev); + longPieces.sort(cmpLenRev); + mixedPieces.sort(cmpLenRev); + for (i = 0; i < 12; i++) { + shortPieces[i] = regexEscape(shortPieces[i]); + longPieces[i] = regexEscape(longPieces[i]); + } + for (i = 0; i < 24; i++) { + mixedPieces[i] = regexEscape(mixedPieces[i]); + } + + this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); + this._monthsShortRegex = this._monthsRegex; + this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); + this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); + } + + // FORMATTING + + addFormatToken('Y', 0, 0, function () { + var y = this.year(); + return y <= 9999 ? '' + y : '+' + y; + }); + + addFormatToken(0, ['YY', 2], 0, function () { + return this.year() % 100; + }); + + addFormatToken(0, ['YYYY', 4], 0, 'year'); + addFormatToken(0, ['YYYYY', 5], 0, 'year'); + addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); + + // ALIASES + + addUnitAlias('year', 'y'); + + // PRIORITIES + + addUnitPriority('year', 1); + + // PARSING + + addRegexToken('Y', matchSigned); + addRegexToken('YY', match1to2, match2); + addRegexToken('YYYY', match1to4, match4); + addRegexToken('YYYYY', match1to6, match6); + addRegexToken('YYYYYY', match1to6, match6); + + addParseToken(['YYYYY', 'YYYYYY'], YEAR); + addParseToken('YYYY', function (input, array) { + array[YEAR] = input.length === 2 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input); + }); + addParseToken('YY', function (input, array) { + array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input); + }); + addParseToken('Y', function (input, array) { + array[YEAR] = parseInt(input, 10); + }); + + // HELPERS + + function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; + } + + function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + } + + // HOOKS + + utils_hooks__hooks.parseTwoDigitYear = function (input) { + return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); + }; + + // MOMENTS + + var getSetYear = makeGetSet('FullYear', true); + + function getIsLeapYear () { + return isLeapYear(this.year()); + } + + function createDate (y, m, d, h, M, s, ms) { + //can't just apply() to create a date: + //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply + var date = new Date(y, m, d, h, M, s, ms); + + //the date constructor remaps years 0-99 to 1900-1999 + if (y < 100 && y >= 0 && isFinite(date.getFullYear())) { + date.setFullYear(y); + } + return date; + } + + function createUTCDate (y) { + var date = new Date(Date.UTC.apply(null, arguments)); + + //the Date.UTC function remaps years 0-99 to 1900-1999 + if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) { + date.setUTCFullYear(y); + } + return date; + } + + // start-of-first-week - start-of-year + function firstWeekOffset(year, dow, doy) { + var // first-week day -- which january is always in the first week (4 for iso, 1 for other) + fwd = 7 + dow - doy, + // first-week day local weekday -- which local weekday is fwd + fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7; + + return -fwdlw + fwd - 1; + } + + //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday + function dayOfYearFromWeeks(year, week, weekday, dow, doy) { + var localWeekday = (7 + weekday - dow) % 7, + weekOffset = firstWeekOffset(year, dow, doy), + dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset, + resYear, resDayOfYear; + + if (dayOfYear <= 0) { + resYear = year - 1; + resDayOfYear = daysInYear(resYear) + dayOfYear; + } else if (dayOfYear > daysInYear(year)) { + resYear = year + 1; + resDayOfYear = dayOfYear - daysInYear(year); + } else { + resYear = year; + resDayOfYear = dayOfYear; + } + + return { + year: resYear, + dayOfYear: resDayOfYear + }; + } + + function weekOfYear(mom, dow, doy) { + var weekOffset = firstWeekOffset(mom.year(), dow, doy), + week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1, + resWeek, resYear; + + if (week < 1) { + resYear = mom.year() - 1; + resWeek = week + weeksInYear(resYear, dow, doy); + } else if (week > weeksInYear(mom.year(), dow, doy)) { + resWeek = week - weeksInYear(mom.year(), dow, doy); + resYear = mom.year() + 1; + } else { + resYear = mom.year(); + resWeek = week; + } + + return { + week: resWeek, + year: resYear + }; + } + + function weeksInYear(year, dow, doy) { + var weekOffset = firstWeekOffset(year, dow, doy), + weekOffsetNext = firstWeekOffset(year + 1, dow, doy); + return (daysInYear(year) - weekOffset + weekOffsetNext) / 7; + } + + // FORMATTING + + addFormatToken('w', ['ww', 2], 'wo', 'week'); + addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); + + // ALIASES + + addUnitAlias('week', 'w'); + addUnitAlias('isoWeek', 'W'); + + // PRIORITIES + + addUnitPriority('week', 5); + addUnitPriority('isoWeek', 5); + + // PARSING + + addRegexToken('w', match1to2); + addRegexToken('ww', match1to2, match2); + addRegexToken('W', match1to2); + addRegexToken('WW', match1to2, match2); + + addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) { + week[token.substr(0, 1)] = toInt(input); + }); + + // HELPERS + + // LOCALES + + function localeWeek (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; + } + + var defaultLocaleWeek = { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + }; + + function localeFirstDayOfWeek () { + return this._week.dow; + } + + function localeFirstDayOfYear () { + return this._week.doy; + } + + // MOMENTS + + function getSetWeek (input) { + var week = this.localeData().week(this); + return input == null ? week : this.add((input - week) * 7, 'd'); + } + + function getSetISOWeek (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add((input - week) * 7, 'd'); + } + + // FORMATTING + + addFormatToken('d', 0, 'do', 'day'); + + addFormatToken('dd', 0, 0, function (format) { + return this.localeData().weekdaysMin(this, format); + }); + + addFormatToken('ddd', 0, 0, function (format) { + return this.localeData().weekdaysShort(this, format); + }); + + addFormatToken('dddd', 0, 0, function (format) { + return this.localeData().weekdays(this, format); + }); + + addFormatToken('e', 0, 0, 'weekday'); + addFormatToken('E', 0, 0, 'isoWeekday'); + + // ALIASES + + addUnitAlias('day', 'd'); + addUnitAlias('weekday', 'e'); + addUnitAlias('isoWeekday', 'E'); + + // PRIORITY + addUnitPriority('day', 11); + addUnitPriority('weekday', 11); + addUnitPriority('isoWeekday', 11); + + // PARSING + + addRegexToken('d', match1to2); + addRegexToken('e', match1to2); + addRegexToken('E', match1to2); + addRegexToken('dd', function (isStrict, locale) { + return locale.weekdaysMinRegex(isStrict); + }); + addRegexToken('ddd', function (isStrict, locale) { + return locale.weekdaysShortRegex(isStrict); + }); + addRegexToken('dddd', function (isStrict, locale) { + return locale.weekdaysRegex(isStrict); + }); + + addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) { + var weekday = config._locale.weekdaysParse(input, token, config._strict); + // if we didn't get a weekday name, mark the date as invalid + if (weekday != null) { + week.d = weekday; + } else { + getParsingFlags(config).invalidWeekday = input; + } + }); + + addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) { + week[token] = toInt(input); + }); + + // HELPERS + + function parseWeekday(input, locale) { + if (typeof input !== 'string') { + return input; + } + + if (!isNaN(input)) { + return parseInt(input, 10); + } + + input = locale.weekdaysParse(input); + if (typeof input === 'number') { + return input; + } + + return null; + } + + function parseIsoWeekday(input, locale) { + if (typeof input === 'string') { + return locale.weekdaysParse(input) % 7 || 7; + } + return isNaN(input) ? null : input; + } + + // LOCALES + + var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'); + function localeWeekdays (m, format) { + return isArray(this._weekdays) ? this._weekdays[m.day()] : + this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()]; + } + + var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'); + function localeWeekdaysShort (m) { + return this._weekdaysShort[m.day()]; + } + + var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'); + function localeWeekdaysMin (m) { + return this._weekdaysMin[m.day()]; + } + + function day_of_week__handleStrictParse(weekdayName, format, strict) { + var i, ii, mom, llc = weekdayName.toLocaleLowerCase(); + if (!this._weekdaysParse) { + this._weekdaysParse = []; + this._shortWeekdaysParse = []; + this._minWeekdaysParse = []; + + for (i = 0; i < 7; ++i) { + mom = create_utc__createUTC([2000, 1]).day(i); + this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase(); + this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase(); + this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase(); + } + } + + if (strict) { + if (format === 'dddd') { + ii = indexOf.call(this._weekdaysParse, llc); + return ii !== -1 ? ii : null; + } else if (format === 'ddd') { + ii = indexOf.call(this._shortWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } + } else { + if (format === 'dddd') { + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else if (format === 'ddd') { + ii = indexOf.call(this._shortWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._minWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } + } + } + + function localeWeekdaysParse (weekdayName, format, strict) { + var i, mom, regex; + + if (this._weekdaysParseExact) { + return day_of_week__handleStrictParse.call(this, weekdayName, format, strict); + } + + if (!this._weekdaysParse) { + this._weekdaysParse = []; + this._minWeekdaysParse = []; + this._shortWeekdaysParse = []; + this._fullWeekdaysParse = []; + } + + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + + mom = create_utc__createUTC([2000, 1]).day(i); + if (strict && !this._fullWeekdaysParse[i]) { + this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i'); + this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i'); + this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i'); + } + if (!this._weekdaysParse[i]) { + regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); + this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (!strict && this._weekdaysParse[i].test(weekdayName)) { + return i; + } + } + } + + // MOMENTS + + function getSetDayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + input = parseWeekday(input, this.localeData()); + return this.add(input - day, 'd'); + } else { + return day; + } + } + + function getSetLocaleDayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; + return input == null ? weekday : this.add(input - weekday, 'd'); + } + + function getSetISODayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + + // behaves the same as moment#day except + // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) + // as a setter, sunday should belong to the previous week. + + if (input != null) { + var weekday = parseIsoWeekday(input, this.localeData()); + return this.day(this.day() % 7 ? weekday : weekday - 7); + } else { + return this.day() || 7; + } + } + + var defaultWeekdaysRegex = matchWord; + function weekdaysRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysStrictRegex; + } else { + return this._weekdaysRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysRegex')) { + this._weekdaysRegex = defaultWeekdaysRegex; + } + return this._weekdaysStrictRegex && isStrict ? + this._weekdaysStrictRegex : this._weekdaysRegex; + } + } + + var defaultWeekdaysShortRegex = matchWord; + function weekdaysShortRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysShortStrictRegex; + } else { + return this._weekdaysShortRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysShortRegex')) { + this._weekdaysShortRegex = defaultWeekdaysShortRegex; + } + return this._weekdaysShortStrictRegex && isStrict ? + this._weekdaysShortStrictRegex : this._weekdaysShortRegex; + } + } + + var defaultWeekdaysMinRegex = matchWord; + function weekdaysMinRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysMinStrictRegex; + } else { + return this._weekdaysMinRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysMinRegex')) { + this._weekdaysMinRegex = defaultWeekdaysMinRegex; + } + return this._weekdaysMinStrictRegex && isStrict ? + this._weekdaysMinStrictRegex : this._weekdaysMinRegex; + } + } + + + function computeWeekdaysParse () { + function cmpLenRev(a, b) { + return b.length - a.length; + } + + var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [], + i, mom, minp, shortp, longp; + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + mom = create_utc__createUTC([2000, 1]).day(i); + minp = this.weekdaysMin(mom, ''); + shortp = this.weekdaysShort(mom, ''); + longp = this.weekdays(mom, ''); + minPieces.push(minp); + shortPieces.push(shortp); + longPieces.push(longp); + mixedPieces.push(minp); + mixedPieces.push(shortp); + mixedPieces.push(longp); + } + // Sorting makes sure if one weekday (or abbr) is a prefix of another it + // will match the longer piece. + minPieces.sort(cmpLenRev); + shortPieces.sort(cmpLenRev); + longPieces.sort(cmpLenRev); + mixedPieces.sort(cmpLenRev); + for (i = 0; i < 7; i++) { + shortPieces[i] = regexEscape(shortPieces[i]); + longPieces[i] = regexEscape(longPieces[i]); + mixedPieces[i] = regexEscape(mixedPieces[i]); + } + + this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); + this._weekdaysShortRegex = this._weekdaysRegex; + this._weekdaysMinRegex = this._weekdaysRegex; + + this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); + this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); + this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i'); + } + + // FORMATTING + + function hFormat() { + return this.hours() % 12 || 12; + } + + function kFormat() { + return this.hours() || 24; + } + + addFormatToken('H', ['HH', 2], 0, 'hour'); + addFormatToken('h', ['hh', 2], 0, hFormat); + addFormatToken('k', ['kk', 2], 0, kFormat); + + addFormatToken('hmm', 0, 0, function () { + return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2); + }); + + addFormatToken('hmmss', 0, 0, function () { + return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) + + zeroFill(this.seconds(), 2); + }); + + addFormatToken('Hmm', 0, 0, function () { + return '' + this.hours() + zeroFill(this.minutes(), 2); + }); + + addFormatToken('Hmmss', 0, 0, function () { + return '' + this.hours() + zeroFill(this.minutes(), 2) + + zeroFill(this.seconds(), 2); + }); + + function meridiem (token, lowercase) { + addFormatToken(token, 0, 0, function () { + return this.localeData().meridiem(this.hours(), this.minutes(), lowercase); + }); + } + + meridiem('a', true); + meridiem('A', false); + + // ALIASES + + addUnitAlias('hour', 'h'); + + // PRIORITY + addUnitPriority('hour', 13); + + // PARSING + + function matchMeridiem (isStrict, locale) { + return locale._meridiemParse; + } + + addRegexToken('a', matchMeridiem); + addRegexToken('A', matchMeridiem); + addRegexToken('H', match1to2); + addRegexToken('h', match1to2); + addRegexToken('HH', match1to2, match2); + addRegexToken('hh', match1to2, match2); + + addRegexToken('hmm', match3to4); + addRegexToken('hmmss', match5to6); + addRegexToken('Hmm', match3to4); + addRegexToken('Hmmss', match5to6); + + addParseToken(['H', 'HH'], HOUR); + addParseToken(['a', 'A'], function (input, array, config) { + config._isPm = config._locale.isPM(input); + config._meridiem = input; + }); + addParseToken(['h', 'hh'], function (input, array, config) { + array[HOUR] = toInt(input); + getParsingFlags(config).bigHour = true; + }); + addParseToken('hmm', function (input, array, config) { + var pos = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos)); + array[MINUTE] = toInt(input.substr(pos)); + getParsingFlags(config).bigHour = true; + }); + addParseToken('hmmss', function (input, array, config) { + var pos1 = input.length - 4; + var pos2 = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos1)); + array[MINUTE] = toInt(input.substr(pos1, 2)); + array[SECOND] = toInt(input.substr(pos2)); + getParsingFlags(config).bigHour = true; + }); + addParseToken('Hmm', function (input, array, config) { + var pos = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos)); + array[MINUTE] = toInt(input.substr(pos)); + }); + addParseToken('Hmmss', function (input, array, config) { + var pos1 = input.length - 4; + var pos2 = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos1)); + array[MINUTE] = toInt(input.substr(pos1, 2)); + array[SECOND] = toInt(input.substr(pos2)); + }); + + // LOCALES + + function localeIsPM (input) { + // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays + // Using charAt should be more compatible. + return ((input + '').toLowerCase().charAt(0) === 'p'); + } + + var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i; + function localeMeridiem (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } + } + + + // MOMENTS + + // Setting the hour should keep the time, because the user explicitly + // specified which hour he wants. So trying to maintain the same hour (in + // a new timezone) makes sense. Adding/subtracting hours does not follow + // this rule. + var getSetHour = makeGetSet('Hours', true); + + var baseConfig = { + calendar: defaultCalendar, + longDateFormat: defaultLongDateFormat, + invalidDate: defaultInvalidDate, + ordinal: defaultOrdinal, + ordinalParse: defaultOrdinalParse, + relativeTime: defaultRelativeTime, + + months: defaultLocaleMonths, + monthsShort: defaultLocaleMonthsShort, + + week: defaultLocaleWeek, + + weekdays: defaultLocaleWeekdays, + weekdaysMin: defaultLocaleWeekdaysMin, + weekdaysShort: defaultLocaleWeekdaysShort, + + meridiemParse: defaultLocaleMeridiemParse + }; + + // internal storage for locale config files + var locales = {}; + var globalLocale; + + function normalizeLocale(key) { + return key ? key.toLowerCase().replace('_', '-') : key; + } + + // pick the locale from the array + // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each + // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root + function chooseLocale(names) { + var i = 0, j, next, locale, split; + + while (i < names.length) { + split = normalizeLocale(names[i]).split('-'); + j = split.length; + next = normalizeLocale(names[i + 1]); + next = next ? next.split('-') : null; + while (j > 0) { + locale = loadLocale(split.slice(0, j).join('-')); + if (locale) { + return locale; + } + if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { + //the next array item is better than a shallower substring of this one + break; + } + j--; + } + i++; + } + return null; + } + + function loadLocale(name) { + var oldLocale = null; + // TODO: Find a better way to register and load all the locales in Node + if (!locales[name] && (typeof module !== 'undefined') && + module && module.exports) { + try { + oldLocale = globalLocale._abbr; + require('./locale/' + name); + // because defineLocale currently also sets the global locale, we + // want to undo that for lazy loaded locales + locale_locales__getSetGlobalLocale(oldLocale); + } catch (e) { } + } + return locales[name]; + } + + // This function will load locale and then set the global locale. If + // no arguments are passed in, it will simply return the current global + // locale key. + function locale_locales__getSetGlobalLocale (key, values) { + var data; + if (key) { + if (isUndefined(values)) { + data = locale_locales__getLocale(key); + } + else { + data = defineLocale(key, values); + } + + if (data) { + // moment.duration._locale = moment._locale = data; + globalLocale = data; + } + } + + return globalLocale._abbr; + } + + function defineLocale (name, config) { + if (config !== null) { + var parentConfig = baseConfig; + config.abbr = name; + if (locales[name] != null) { + deprecateSimple('defineLocaleOverride', + 'use moment.updateLocale(localeName, config) to change ' + + 'an existing locale. moment.defineLocale(localeName, ' + + 'config) should only be used for creating a new locale ' + + 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.'); + parentConfig = locales[name]._config; + } else if (config.parentLocale != null) { + if (locales[config.parentLocale] != null) { + parentConfig = locales[config.parentLocale]._config; + } else { + // treat as if there is no base config + deprecateSimple('parentLocaleUndefined', + 'specified parentLocale is not defined yet. See http://momentjs.com/guides/#/warnings/parent-locale/'); + } + } + locales[name] = new Locale(mergeConfigs(parentConfig, config)); + + // backwards compat for now: also set the locale + locale_locales__getSetGlobalLocale(name); + + return locales[name]; + } else { + // useful for testing + delete locales[name]; + return null; + } + } + + function updateLocale(name, config) { + if (config != null) { + var locale, parentConfig = baseConfig; + // MERGE + if (locales[name] != null) { + parentConfig = locales[name]._config; + } + config = mergeConfigs(parentConfig, config); + locale = new Locale(config); + locale.parentLocale = locales[name]; + locales[name] = locale; + + // backwards compat for now: also set the locale + locale_locales__getSetGlobalLocale(name); + } else { + // pass null for config to unupdate, useful for tests + if (locales[name] != null) { + if (locales[name].parentLocale != null) { + locales[name] = locales[name].parentLocale; + } else if (locales[name] != null) { + delete locales[name]; + } + } + } + return locales[name]; + } + + // returns locale data + function locale_locales__getLocale (key) { + var locale; + + if (key && key._locale && key._locale._abbr) { + key = key._locale._abbr; + } + + if (!key) { + return globalLocale; + } + + if (!isArray(key)) { + //short-circuit everything else + locale = loadLocale(key); + if (locale) { + return locale; + } + key = [key]; + } + + return chooseLocale(key); + } + + function locale_locales__listLocales() { + return keys(locales); + } + + function checkOverflow (m) { + var overflow; + var a = m._a; + + if (a && getParsingFlags(m).overflow === -2) { + overflow = + a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : + a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : + a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR : + a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : + a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : + a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : + -1; + + if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } + if (getParsingFlags(m)._overflowWeeks && overflow === -1) { + overflow = WEEK; + } + if (getParsingFlags(m)._overflowWeekday && overflow === -1) { + overflow = WEEKDAY; + } + + getParsingFlags(m).overflow = overflow; + } + + return m; + } + + // iso 8601 regex + // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) + var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/; + var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/; + + var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/; + + var isoDates = [ + ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], + ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], + ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], + ['GGGG-[W]WW', /\d{4}-W\d\d/, false], + ['YYYY-DDD', /\d{4}-\d{3}/], + ['YYYY-MM', /\d{4}-\d\d/, false], + ['YYYYYYMMDD', /[+-]\d{10}/], + ['YYYYMMDD', /\d{8}/], + // YYYYMM is NOT allowed by the standard + ['GGGG[W]WWE', /\d{4}W\d{3}/], + ['GGGG[W]WW', /\d{4}W\d{2}/, false], + ['YYYYDDD', /\d{7}/] + ]; + + // iso time formats and regexes + var isoTimes = [ + ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], + ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], + ['HH:mm:ss', /\d\d:\d\d:\d\d/], + ['HH:mm', /\d\d:\d\d/], + ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], + ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], + ['HHmmss', /\d\d\d\d\d\d/], + ['HHmm', /\d\d\d\d/], + ['HH', /\d\d/] + ]; + + var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; + + // date from iso format + function configFromISO(config) { + var i, l, + string = config._i, + match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string), + allowTime, dateFormat, timeFormat, tzFormat; + + if (match) { + getParsingFlags(config).iso = true; + + for (i = 0, l = isoDates.length; i < l; i++) { + if (isoDates[i][1].exec(match[1])) { + dateFormat = isoDates[i][0]; + allowTime = isoDates[i][2] !== false; + break; + } + } + if (dateFormat == null) { + config._isValid = false; + return; + } + if (match[3]) { + for (i = 0, l = isoTimes.length; i < l; i++) { + if (isoTimes[i][1].exec(match[3])) { + // match[2] should be 'T' or space + timeFormat = (match[2] || ' ') + isoTimes[i][0]; + break; + } + } + if (timeFormat == null) { + config._isValid = false; + return; + } + } + if (!allowTime && timeFormat != null) { + config._isValid = false; + return; + } + if (match[4]) { + if (tzRegex.exec(match[4])) { + tzFormat = 'Z'; + } else { + config._isValid = false; + return; + } + } + config._f = dateFormat + (timeFormat || '') + (tzFormat || ''); + configFromStringAndFormat(config); + } else { + config._isValid = false; + } + } + + // date from iso format or fallback + function configFromString(config) { + var matched = aspNetJsonRegex.exec(config._i); + + if (matched !== null) { + config._d = new Date(+matched[1]); + return; + } + + configFromISO(config); + if (config._isValid === false) { + delete config._isValid; + utils_hooks__hooks.createFromInputFallback(config); + } + } + + utils_hooks__hooks.createFromInputFallback = deprecate( + 'moment construction falls back to js Date. This is ' + + 'discouraged and will be removed in upcoming major ' + + 'release. Please refer to ' + + 'http://momentjs.com/guides/#/warnings/js-date/ for more info.', + function (config) { + config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); + } + ); + + // Pick the first defined of two or three arguments. + function defaults(a, b, c) { + if (a != null) { + return a; + } + if (b != null) { + return b; + } + return c; + } + + function currentDateArray(config) { + // hooks is actually the exported moment object + var nowValue = new Date(utils_hooks__hooks.now()); + if (config._useUTC) { + return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()]; + } + return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()]; + } + + // convert an array to a date. + // the array should mirror the parameters below + // note: all values past the year are optional and will default to the lowest possible value. + // [year, month, day , hour, minute, second, millisecond] + function configFromArray (config) { + var i, date, input = [], currentDate, yearToUse; + + if (config._d) { + return; + } + + currentDate = currentDateArray(config); + + //compute day of the year from weeks and weekdays + if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { + dayOfYearFromWeekInfo(config); + } + + //if the day of the year is set, figure out what it is + if (config._dayOfYear) { + yearToUse = defaults(config._a[YEAR], currentDate[YEAR]); + + if (config._dayOfYear > daysInYear(yearToUse)) { + getParsingFlags(config)._overflowDayOfYear = true; + } + + date = createUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); + } + + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } + + // Zero out whatever was not defaulted, including time + for (; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } + + // Check for 24:00:00.000 + if (config._a[HOUR] === 24 && + config._a[MINUTE] === 0 && + config._a[SECOND] === 0 && + config._a[MILLISECOND] === 0) { + config._nextDay = true; + config._a[HOUR] = 0; + } + + config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input); + // Apply timezone offset from input. The actual utcOffset can be changed + // with parseZone. + if (config._tzm != null) { + config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); + } + + if (config._nextDay) { + config._a[HOUR] = 24; + } + } + + function dayOfYearFromWeekInfo(config) { + var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow; + + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + dow = 1; + doy = 4; + + // TODO: We need to take the current isoWeekYear, but that depends on + // how we interpret now (local, utc, fixed offset). So create + // a now version of current config (take local/utc/offset flags, and + // create now). + weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year); + week = defaults(w.W, 1); + weekday = defaults(w.E, 1); + if (weekday < 1 || weekday > 7) { + weekdayOverflow = true; + } + } else { + dow = config._locale._week.dow; + doy = config._locale._week.doy; + + weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year); + week = defaults(w.w, 1); + + if (w.d != null) { + // weekday -- low day numbers are considered next week + weekday = w.d; + if (weekday < 0 || weekday > 6) { + weekdayOverflow = true; + } + } else if (w.e != null) { + // local weekday -- counting starts from begining of week + weekday = w.e + dow; + if (w.e < 0 || w.e > 6) { + weekdayOverflow = true; + } + } else { + // default to begining of week + weekday = dow; + } + } + if (week < 1 || week > weeksInYear(weekYear, dow, doy)) { + getParsingFlags(config)._overflowWeeks = true; + } else if (weekdayOverflow != null) { + getParsingFlags(config)._overflowWeekday = true; + } else { + temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy); + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; + } + } + + // constant that refers to the ISO standard + utils_hooks__hooks.ISO_8601 = function () {}; + + // date from string and format string + function configFromStringAndFormat(config) { + // TODO: Move this to another part of the creation flow to prevent circular deps + if (config._f === utils_hooks__hooks.ISO_8601) { + configFromISO(config); + return; + } + + config._a = []; + getParsingFlags(config).empty = true; + + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var string = '' + config._i, + i, parsedInput, tokens, token, skipped, + stringLength = string.length, + totalParsedInputLength = 0; + + tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; + + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; + // console.log('token', token, 'parsedInput', parsedInput, + // 'regex', getParseRegexForToken(token, config)); + if (parsedInput) { + skipped = string.substr(0, string.indexOf(parsedInput)); + if (skipped.length > 0) { + getParsingFlags(config).unusedInput.push(skipped); + } + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); + totalParsedInputLength += parsedInput.length; + } + // don't parse if it's not a known token + if (formatTokenFunctions[token]) { + if (parsedInput) { + getParsingFlags(config).empty = false; + } + else { + getParsingFlags(config).unusedTokens.push(token); + } + addTimeToArrayFromToken(token, parsedInput, config); + } + else if (config._strict && !parsedInput) { + getParsingFlags(config).unusedTokens.push(token); + } + } + + // add remaining unparsed input length to the string + getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + getParsingFlags(config).unusedInput.push(string); + } + + // clear _12h flag if hour is <= 12 + if (config._a[HOUR] <= 12 && + getParsingFlags(config).bigHour === true && + config._a[HOUR] > 0) { + getParsingFlags(config).bigHour = undefined; + } + + getParsingFlags(config).parsedDateParts = config._a.slice(0); + getParsingFlags(config).meridiem = config._meridiem; + // handle meridiem + config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem); + + configFromArray(config); + checkOverflow(config); + } + + + function meridiemFixWrap (locale, hour, meridiem) { + var isPm; + + if (meridiem == null) { + // nothing to do + return hour; + } + if (locale.meridiemHour != null) { + return locale.meridiemHour(hour, meridiem); + } else if (locale.isPM != null) { + // Fallback + isPm = locale.isPM(meridiem); + if (isPm && hour < 12) { + hour += 12; + } + if (!isPm && hour === 12) { + hour = 0; + } + return hour; + } else { + // this is not supposed to happen + return hour; + } + } + + // date from string and array of format strings + function configFromStringAndArray(config) { + var tempConfig, + bestMoment, + + scoreToBeat, + i, + currentScore; + + if (config._f.length === 0) { + getParsingFlags(config).invalidFormat = true; + config._d = new Date(NaN); + return; + } + + for (i = 0; i < config._f.length; i++) { + currentScore = 0; + tempConfig = copyConfig({}, config); + if (config._useUTC != null) { + tempConfig._useUTC = config._useUTC; + } + tempConfig._f = config._f[i]; + configFromStringAndFormat(tempConfig); + + if (!valid__isValid(tempConfig)) { + continue; + } + + // if there is any input that was not parsed add a penalty for that format + currentScore += getParsingFlags(tempConfig).charsLeftOver; + + //or tokens + currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10; + + getParsingFlags(tempConfig).score = currentScore; + + if (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } + } + + extend(config, bestMoment || tempConfig); + } + + function configFromObject(config) { + if (config._d) { + return; + } + + var i = normalizeObjectUnits(config._i); + config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) { + return obj && parseInt(obj, 10); + }); + + configFromArray(config); + } + + function createFromConfig (config) { + var res = new Moment(checkOverflow(prepareConfig(config))); + if (res._nextDay) { + // Adding is smart enough around DST + res.add(1, 'd'); + res._nextDay = undefined; + } + + return res; + } + + function prepareConfig (config) { + var input = config._i, + format = config._f; + + config._locale = config._locale || locale_locales__getLocale(config._l); + + if (input === null || (format === undefined && input === '')) { + return valid__createInvalid({nullInput: true}); + } + + if (typeof input === 'string') { + config._i = input = config._locale.preparse(input); + } + + if (isMoment(input)) { + return new Moment(checkOverflow(input)); + } else if (isArray(format)) { + configFromStringAndArray(config); + } else if (isDate(input)) { + config._d = input; + } else if (format) { + configFromStringAndFormat(config); + } else { + configFromInput(config); + } + + if (!valid__isValid(config)) { + config._d = null; + } + + return config; + } + + function configFromInput(config) { + var input = config._i; + if (input === undefined) { + config._d = new Date(utils_hooks__hooks.now()); + } else if (isDate(input)) { + config._d = new Date(input.valueOf()); + } else if (typeof input === 'string') { + configFromString(config); + } else if (isArray(input)) { + config._a = map(input.slice(0), function (obj) { + return parseInt(obj, 10); + }); + configFromArray(config); + } else if (typeof(input) === 'object') { + configFromObject(config); + } else if (typeof(input) === 'number') { + // from milliseconds + config._d = new Date(input); + } else { + utils_hooks__hooks.createFromInputFallback(config); + } + } + + function createLocalOrUTC (input, format, locale, strict, isUTC) { + var c = {}; + + if (typeof(locale) === 'boolean') { + strict = locale; + locale = undefined; + } + + if ((isObject(input) && isObjectEmpty(input)) || + (isArray(input) && input.length === 0)) { + input = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c._isAMomentObject = true; + c._useUTC = c._isUTC = isUTC; + c._l = locale; + c._i = input; + c._f = format; + c._strict = strict; + + return createFromConfig(c); + } + + function local__createLocal (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, false); + } + + var prototypeMin = deprecate( + 'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/', + function () { + var other = local__createLocal.apply(null, arguments); + if (this.isValid() && other.isValid()) { + return other < this ? this : other; + } else { + return valid__createInvalid(); + } + } + ); + + var prototypeMax = deprecate( + 'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/', + function () { + var other = local__createLocal.apply(null, arguments); + if (this.isValid() && other.isValid()) { + return other > this ? this : other; + } else { + return valid__createInvalid(); + } + } + ); + + // Pick a moment m from moments so that m[fn](other) is true for all + // other. This relies on the function fn to be transitive. + // + // moments should either be an array of moment objects or an array, whose + // first element is an array of moment objects. + function pickBy(fn, moments) { + var res, i; + if (moments.length === 1 && isArray(moments[0])) { + moments = moments[0]; + } + if (!moments.length) { + return local__createLocal(); + } + res = moments[0]; + for (i = 1; i < moments.length; ++i) { + if (!moments[i].isValid() || moments[i][fn](res)) { + res = moments[i]; + } + } + return res; + } + + // TODO: Use [].sort instead? + function min () { + var args = [].slice.call(arguments, 0); + + return pickBy('isBefore', args); + } + + function max () { + var args = [].slice.call(arguments, 0); + + return pickBy('isAfter', args); + } + + var now = function () { + return Date.now ? Date.now() : +(new Date()); + }; + + function Duration (duration) { + var normalizedInput = normalizeObjectUnits(duration), + years = normalizedInput.year || 0, + quarters = normalizedInput.quarter || 0, + months = normalizedInput.month || 0, + weeks = normalizedInput.week || 0, + days = normalizedInput.day || 0, + hours = normalizedInput.hour || 0, + minutes = normalizedInput.minute || 0, + seconds = normalizedInput.second || 0, + milliseconds = normalizedInput.millisecond || 0; + + // representation for dateAddRemove + this._milliseconds = +milliseconds + + seconds * 1e3 + // 1000 + minutes * 6e4 + // 1000 * 60 + hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978 + // Because of dateAddRemove treats 24 hours as different from a + // day when working around DST, we need to store them separately + this._days = +days + + weeks * 7; + // It is impossible translate months into days without knowing + // which months you are are talking about, so we have to store + // it separately. + this._months = +months + + quarters * 3 + + years * 12; + + this._data = {}; + + this._locale = locale_locales__getLocale(); + + this._bubble(); + } + + function isDuration (obj) { + return obj instanceof Duration; + } + + // FORMATTING + + function offset (token, separator) { + addFormatToken(token, 0, 0, function () { + var offset = this.utcOffset(); + var sign = '+'; + if (offset < 0) { + offset = -offset; + sign = '-'; + } + return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2); + }); + } + + offset('Z', ':'); + offset('ZZ', ''); + + // PARSING + + addRegexToken('Z', matchShortOffset); + addRegexToken('ZZ', matchShortOffset); + addParseToken(['Z', 'ZZ'], function (input, array, config) { + config._useUTC = true; + config._tzm = offsetFromString(matchShortOffset, input); + }); + + // HELPERS + + // timezone chunker + // '+10:00' > ['10', '00'] + // '-1530' > ['-15', '30'] + var chunkOffset = /([\+\-]|\d\d)/gi; + + function offsetFromString(matcher, string) { + var matches = ((string || '').match(matcher) || []); + var chunk = matches[matches.length - 1] || []; + var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0]; + var minutes = +(parts[1] * 60) + toInt(parts[2]); + + return parts[0] === '+' ? minutes : -minutes; + } + + // Return a moment from input, that is local/utc/zone equivalent to model. + function cloneWithOffset(input, model) { + var res, diff; + if (model._isUTC) { + res = model.clone(); + diff = (isMoment(input) || isDate(input) ? input.valueOf() : local__createLocal(input).valueOf()) - res.valueOf(); + // Use low-level api, because this fn is low-level api. + res._d.setTime(res._d.valueOf() + diff); + utils_hooks__hooks.updateOffset(res, false); + return res; + } else { + return local__createLocal(input).local(); + } + } + + function getDateOffset (m) { + // On Firefox.24 Date#getTimezoneOffset returns a floating point. + // https://github.com/moment/moment/pull/1871 + return -Math.round(m._d.getTimezoneOffset() / 15) * 15; + } + + // HOOKS + + // This function will be called whenever a moment is mutated. + // It is intended to keep the offset in sync with the timezone. + utils_hooks__hooks.updateOffset = function () {}; + + // MOMENTS + + // keepLocalTime = true means only change the timezone, without + // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> + // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset + // +0200, so we adjust the time as needed, to be valid. + // + // Keeping the time actually adds/subtracts (one hour) + // from the actual represented time. That is why we call updateOffset + // a second time. In case it wants us to change the offset again + // _changeInProgress == true case, then we have to adjust, because + // there is no such time in the given timezone. + function getSetOffset (input, keepLocalTime) { + var offset = this._offset || 0, + localAdjust; + if (!this.isValid()) { + return input != null ? this : NaN; + } + if (input != null) { + if (typeof input === 'string') { + input = offsetFromString(matchShortOffset, input); + } else if (Math.abs(input) < 16) { + input = input * 60; + } + if (!this._isUTC && keepLocalTime) { + localAdjust = getDateOffset(this); + } + this._offset = input; + this._isUTC = true; + if (localAdjust != null) { + this.add(localAdjust, 'm'); + } + if (offset !== input) { + if (!keepLocalTime || this._changeInProgress) { + add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false); + } else if (!this._changeInProgress) { + this._changeInProgress = true; + utils_hooks__hooks.updateOffset(this, true); + this._changeInProgress = null; + } + } + return this; + } else { + return this._isUTC ? offset : getDateOffset(this); + } + } + + function getSetZone (input, keepLocalTime) { + if (input != null) { + if (typeof input !== 'string') { + input = -input; + } + + this.utcOffset(input, keepLocalTime); + + return this; + } else { + return -this.utcOffset(); + } + } + + function setOffsetToUTC (keepLocalTime) { + return this.utcOffset(0, keepLocalTime); + } + + function setOffsetToLocal (keepLocalTime) { + if (this._isUTC) { + this.utcOffset(0, keepLocalTime); + this._isUTC = false; + + if (keepLocalTime) { + this.subtract(getDateOffset(this), 'm'); + } + } + return this; + } + + function setOffsetToParsedOffset () { + if (this._tzm) { + this.utcOffset(this._tzm); + } else if (typeof this._i === 'string') { + this.utcOffset(offsetFromString(matchOffset, this._i)); + } + return this; + } + + function hasAlignedHourOffset (input) { + if (!this.isValid()) { + return false; + } + input = input ? local__createLocal(input).utcOffset() : 0; + + return (this.utcOffset() - input) % 60 === 0; + } + + function isDaylightSavingTime () { + return ( + this.utcOffset() > this.clone().month(0).utcOffset() || + this.utcOffset() > this.clone().month(5).utcOffset() + ); + } + + function isDaylightSavingTimeShifted () { + if (!isUndefined(this._isDSTShifted)) { + return this._isDSTShifted; + } + + var c = {}; + + copyConfig(c, this); + c = prepareConfig(c); + + if (c._a) { + var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a); + this._isDSTShifted = this.isValid() && + compareArrays(c._a, other.toArray()) > 0; + } else { + this._isDSTShifted = false; + } + + return this._isDSTShifted; + } + + function isLocal () { + return this.isValid() ? !this._isUTC : false; + } + + function isUtcOffset () { + return this.isValid() ? this._isUTC : false; + } + + function isUtc () { + return this.isValid() ? this._isUTC && this._offset === 0 : false; + } + + // ASP.NET json date format regex + var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/; + + // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html + // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere + // and further modified to allow for strings containing both week and day + var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/; + + function create__createDuration (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + diffRes; + + if (isDuration(input)) { + duration = { + ms : input._milliseconds, + d : input._days, + M : input._months + }; + } else if (typeof input === 'number') { + duration = {}; + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (!!(match = aspNetRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : 0, + d : toInt(match[DATE]) * sign, + h : toInt(match[HOUR]) * sign, + m : toInt(match[MINUTE]) * sign, + s : toInt(match[SECOND]) * sign, + ms : toInt(match[MILLISECOND]) * sign + }; + } else if (!!(match = isoRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : parseIso(match[2], sign), + M : parseIso(match[3], sign), + w : parseIso(match[4], sign), + d : parseIso(match[5], sign), + h : parseIso(match[6], sign), + m : parseIso(match[7], sign), + s : parseIso(match[8], sign) + }; + } else if (duration == null) {// checks for null or undefined + duration = {}; + } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) { + diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to)); + + duration = {}; + duration.ms = diffRes.milliseconds; + duration.M = diffRes.months; + } + + ret = new Duration(duration); + + if (isDuration(input) && hasOwnProp(input, '_locale')) { + ret._locale = input._locale; + } + + return ret; + } + + create__createDuration.fn = Duration.prototype; + + function parseIso (inp, sign) { + // We'd normally use ~~inp for this, but unfortunately it also + // converts floats to ints. + // inp may be undefined, so careful calling replace on it. + var res = inp && parseFloat(inp.replace(',', '.')); + // apply sign while we're at it + return (isNaN(res) ? 0 : res) * sign; + } + + function positiveMomentsDifference(base, other) { + var res = {milliseconds: 0, months: 0}; + + res.months = other.month() - base.month() + + (other.year() - base.year()) * 12; + if (base.clone().add(res.months, 'M').isAfter(other)) { + --res.months; + } + + res.milliseconds = +other - +(base.clone().add(res.months, 'M')); + + return res; + } + + function momentsDifference(base, other) { + var res; + if (!(base.isValid() && other.isValid())) { + return {milliseconds: 0, months: 0}; + } + + other = cloneWithOffset(other, base); + if (base.isBefore(other)) { + res = positiveMomentsDifference(base, other); + } else { + res = positiveMomentsDifference(other, base); + res.milliseconds = -res.milliseconds; + res.months = -res.months; + } + + return res; + } + + function absRound (number) { + if (number < 0) { + return Math.round(-1 * number) * -1; + } else { + return Math.round(number); + } + } + + // TODO: remove 'name' arg after deprecation is removed + function createAdder(direction, name) { + return function (val, period) { + var dur, tmp; + //invert the arguments, but complain about it + if (period !== null && !isNaN(+period)) { + deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' + + 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.'); + tmp = val; val = period; period = tmp; + } + + val = typeof val === 'string' ? +val : val; + dur = create__createDuration(val, period); + add_subtract__addSubtract(this, dur, direction); + return this; + }; + } + + function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) { + var milliseconds = duration._milliseconds, + days = absRound(duration._days), + months = absRound(duration._months); + + if (!mom.isValid()) { + // No op + return; + } + + updateOffset = updateOffset == null ? true : updateOffset; + + if (milliseconds) { + mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding); + } + if (days) { + get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding); + } + if (months) { + setMonth(mom, get_set__get(mom, 'Month') + months * isAdding); + } + if (updateOffset) { + utils_hooks__hooks.updateOffset(mom, days || months); + } + } + + var add_subtract__add = createAdder(1, 'add'); + var add_subtract__subtract = createAdder(-1, 'subtract'); + + function getCalendarFormat(myMoment, now) { + var diff = myMoment.diff(now, 'days', true); + return diff < -6 ? 'sameElse' : + diff < -1 ? 'lastWeek' : + diff < 0 ? 'lastDay' : + diff < 1 ? 'sameDay' : + diff < 2 ? 'nextDay' : + diff < 7 ? 'nextWeek' : 'sameElse'; + } + + function moment_calendar__calendar (time, formats) { + // We want to compare the start of today, vs this. + // Getting start-of-today depends on whether we're local/utc/offset or not. + var now = time || local__createLocal(), + sod = cloneWithOffset(now, this).startOf('day'), + format = utils_hooks__hooks.calendarFormat(this, sod) || 'sameElse'; + + var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]); + + return this.format(output || this.localeData().calendar(format, this, local__createLocal(now))); + } + + function clone () { + return new Moment(this); + } + + function isAfter (input, units) { + var localInput = isMoment(input) ? input : local__createLocal(input); + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(!isUndefined(units) ? units : 'millisecond'); + if (units === 'millisecond') { + return this.valueOf() > localInput.valueOf(); + } else { + return localInput.valueOf() < this.clone().startOf(units).valueOf(); + } + } + + function isBefore (input, units) { + var localInput = isMoment(input) ? input : local__createLocal(input); + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(!isUndefined(units) ? units : 'millisecond'); + if (units === 'millisecond') { + return this.valueOf() < localInput.valueOf(); + } else { + return this.clone().endOf(units).valueOf() < localInput.valueOf(); + } + } + + function isBetween (from, to, units, inclusivity) { + inclusivity = inclusivity || '()'; + return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) && + (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units)); + } + + function isSame (input, units) { + var localInput = isMoment(input) ? input : local__createLocal(input), + inputMs; + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(units || 'millisecond'); + if (units === 'millisecond') { + return this.valueOf() === localInput.valueOf(); + } else { + inputMs = localInput.valueOf(); + return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf(); + } + } + + function isSameOrAfter (input, units) { + return this.isSame(input, units) || this.isAfter(input,units); + } + + function isSameOrBefore (input, units) { + return this.isSame(input, units) || this.isBefore(input,units); + } + + function diff (input, units, asFloat) { + var that, + zoneDelta, + delta, output; + + if (!this.isValid()) { + return NaN; + } + + that = cloneWithOffset(input, this); + + if (!that.isValid()) { + return NaN; + } + + zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4; + + units = normalizeUnits(units); + + if (units === 'year' || units === 'month' || units === 'quarter') { + output = monthDiff(this, that); + if (units === 'quarter') { + output = output / 3; + } else if (units === 'year') { + output = output / 12; + } + } else { + delta = this - that; + output = units === 'second' ? delta / 1e3 : // 1000 + units === 'minute' ? delta / 6e4 : // 1000 * 60 + units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60 + units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst + units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst + delta; + } + return asFloat ? output : absFloor(output); + } + + function monthDiff (a, b) { + // difference in months + var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()), + // b is in (anchor - 1 month, anchor + 1 month) + anchor = a.clone().add(wholeMonthDiff, 'months'), + anchor2, adjust; + + if (b - anchor < 0) { + anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor - anchor2); + } else { + anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor2 - anchor); + } + + //check for negative zero, return zero if negative zero + return -(wholeMonthDiff + adjust) || 0; + } + + utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ'; + utils_hooks__hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]'; + + function toString () { + return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); + } + + function moment_format__toISOString () { + var m = this.clone().utc(); + if (0 < m.year() && m.year() <= 9999) { + if (isFunction(Date.prototype.toISOString)) { + // native implementation is ~50x faster, use it when we can + return this.toDate().toISOString(); + } else { + return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + } else { + return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + } + + function moment_format__format (inputString) { + if (!inputString) { + inputString = this.isUtc() ? utils_hooks__hooks.defaultFormatUtc : utils_hooks__hooks.defaultFormat; + } + var output = formatMoment(this, inputString); + return this.localeData().postformat(output); + } + + function from (time, withoutSuffix) { + if (this.isValid() && + ((isMoment(time) && time.isValid()) || + local__createLocal(time).isValid())) { + return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); + } else { + return this.localeData().invalidDate(); + } + } + + function fromNow (withoutSuffix) { + return this.from(local__createLocal(), withoutSuffix); + } + + function to (time, withoutSuffix) { + if (this.isValid() && + ((isMoment(time) && time.isValid()) || + local__createLocal(time).isValid())) { + return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix); + } else { + return this.localeData().invalidDate(); + } + } + + function toNow (withoutSuffix) { + return this.to(local__createLocal(), withoutSuffix); + } + + // If passed a locale key, it will set the locale for this + // instance. Otherwise, it will return the locale configuration + // variables for this instance. + function locale (key) { + var newLocaleData; + + if (key === undefined) { + return this._locale._abbr; + } else { + newLocaleData = locale_locales__getLocale(key); + if (newLocaleData != null) { + this._locale = newLocaleData; + } + return this; + } + } + + var lang = deprecate( + 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', + function (key) { + if (key === undefined) { + return this.localeData(); + } else { + return this.locale(key); + } + } + ); + + function localeData () { + return this._locale; + } + + function startOf (units) { + units = normalizeUnits(units); + // the following switch intentionally omits break keywords + // to utilize falling through the cases. + switch (units) { + case 'year': + this.month(0); + /* falls through */ + case 'quarter': + case 'month': + this.date(1); + /* falls through */ + case 'week': + case 'isoWeek': + case 'day': + case 'date': + this.hours(0); + /* falls through */ + case 'hour': + this.minutes(0); + /* falls through */ + case 'minute': + this.seconds(0); + /* falls through */ + case 'second': + this.milliseconds(0); + } + + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } + if (units === 'isoWeek') { + this.isoWeekday(1); + } + + // quarters are also special + if (units === 'quarter') { + this.month(Math.floor(this.month() / 3) * 3); + } + + return this; + } + + function endOf (units) { + units = normalizeUnits(units); + if (units === undefined || units === 'millisecond') { + return this; + } + + // 'date' is an alias for 'day', so it should be considered as such. + if (units === 'date') { + units = 'day'; + } + + return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); + } + + function to_type__valueOf () { + return this._d.valueOf() - ((this._offset || 0) * 60000); + } + + function unix () { + return Math.floor(this.valueOf() / 1000); + } + + function toDate () { + return new Date(this.valueOf()); + } + + function toArray () { + var m = this; + return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()]; + } + + function toObject () { + var m = this; + return { + years: m.year(), + months: m.month(), + date: m.date(), + hours: m.hours(), + minutes: m.minutes(), + seconds: m.seconds(), + milliseconds: m.milliseconds() + }; + } + + function toJSON () { + // new Date(NaN).toJSON() === null + return this.isValid() ? this.toISOString() : null; + } + + function moment_valid__isValid () { + return valid__isValid(this); + } + + function parsingFlags () { + return extend({}, getParsingFlags(this)); + } + + function invalidAt () { + return getParsingFlags(this).overflow; + } + + function creationData() { + return { + input: this._i, + format: this._f, + locale: this._locale, + isUTC: this._isUTC, + strict: this._strict + }; + } + + // FORMATTING + + addFormatToken(0, ['gg', 2], 0, function () { + return this.weekYear() % 100; + }); + + addFormatToken(0, ['GG', 2], 0, function () { + return this.isoWeekYear() % 100; + }); + + function addWeekYearFormatToken (token, getter) { + addFormatToken(0, [token, token.length], 0, getter); + } + + addWeekYearFormatToken('gggg', 'weekYear'); + addWeekYearFormatToken('ggggg', 'weekYear'); + addWeekYearFormatToken('GGGG', 'isoWeekYear'); + addWeekYearFormatToken('GGGGG', 'isoWeekYear'); + + // ALIASES + + addUnitAlias('weekYear', 'gg'); + addUnitAlias('isoWeekYear', 'GG'); + + // PRIORITY + + addUnitPriority('weekYear', 1); + addUnitPriority('isoWeekYear', 1); + + + // PARSING + + addRegexToken('G', matchSigned); + addRegexToken('g', matchSigned); + addRegexToken('GG', match1to2, match2); + addRegexToken('gg', match1to2, match2); + addRegexToken('GGGG', match1to4, match4); + addRegexToken('gggg', match1to4, match4); + addRegexToken('GGGGG', match1to6, match6); + addRegexToken('ggggg', match1to6, match6); + + addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) { + week[token.substr(0, 2)] = toInt(input); + }); + + addWeekParseToken(['gg', 'GG'], function (input, week, config, token) { + week[token] = utils_hooks__hooks.parseTwoDigitYear(input); + }); + + // MOMENTS + + function getSetWeekYear (input) { + return getSetWeekYearHelper.call(this, + input, + this.week(), + this.weekday(), + this.localeData()._week.dow, + this.localeData()._week.doy); + } + + function getSetISOWeekYear (input) { + return getSetWeekYearHelper.call(this, + input, this.isoWeek(), this.isoWeekday(), 1, 4); + } + + function getISOWeeksInYear () { + return weeksInYear(this.year(), 1, 4); + } + + function getWeeksInYear () { + var weekInfo = this.localeData()._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); + } + + function getSetWeekYearHelper(input, week, weekday, dow, doy) { + var weeksTarget; + if (input == null) { + return weekOfYear(this, dow, doy).year; + } else { + weeksTarget = weeksInYear(input, dow, doy); + if (week > weeksTarget) { + week = weeksTarget; + } + return setWeekAll.call(this, input, week, weekday, dow, doy); + } + } + + function setWeekAll(weekYear, week, weekday, dow, doy) { + var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy), + date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear); + + this.year(date.getUTCFullYear()); + this.month(date.getUTCMonth()); + this.date(date.getUTCDate()); + return this; + } + + // FORMATTING + + addFormatToken('Q', 0, 'Qo', 'quarter'); + + // ALIASES + + addUnitAlias('quarter', 'Q'); + + // PRIORITY + + addUnitPriority('quarter', 7); + + // PARSING + + addRegexToken('Q', match1); + addParseToken('Q', function (input, array) { + array[MONTH] = (toInt(input) - 1) * 3; + }); + + // MOMENTS + + function getSetQuarter (input) { + return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); + } + + // FORMATTING + + addFormatToken('D', ['DD', 2], 'Do', 'date'); + + // ALIASES + + addUnitAlias('date', 'D'); + + // PRIOROITY + addUnitPriority('date', 9); + + // PARSING + + addRegexToken('D', match1to2); + addRegexToken('DD', match1to2, match2); + addRegexToken('Do', function (isStrict, locale) { + return isStrict ? locale._ordinalParse : locale._ordinalParseLenient; + }); + + addParseToken(['D', 'DD'], DATE); + addParseToken('Do', function (input, array) { + array[DATE] = toInt(input.match(match1to2)[0], 10); + }); + + // MOMENTS + + var getSetDayOfMonth = makeGetSet('Date', true); + + // FORMATTING + + addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); + + // ALIASES + + addUnitAlias('dayOfYear', 'DDD'); + + // PRIORITY + addUnitPriority('dayOfYear', 4); + + // PARSING + + addRegexToken('DDD', match1to3); + addRegexToken('DDDD', match3); + addParseToken(['DDD', 'DDDD'], function (input, array, config) { + config._dayOfYear = toInt(input); + }); + + // HELPERS + + // MOMENTS + + function getSetDayOfYear (input) { + var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); + } + + // FORMATTING + + addFormatToken('m', ['mm', 2], 0, 'minute'); + + // ALIASES + + addUnitAlias('minute', 'm'); + + // PRIORITY + + addUnitPriority('minute', 14); + + // PARSING + + addRegexToken('m', match1to2); + addRegexToken('mm', match1to2, match2); + addParseToken(['m', 'mm'], MINUTE); + + // MOMENTS + + var getSetMinute = makeGetSet('Minutes', false); + + // FORMATTING + + addFormatToken('s', ['ss', 2], 0, 'second'); + + // ALIASES + + addUnitAlias('second', 's'); + + // PRIORITY + + addUnitPriority('second', 15); + + // PARSING + + addRegexToken('s', match1to2); + addRegexToken('ss', match1to2, match2); + addParseToken(['s', 'ss'], SECOND); + + // MOMENTS + + var getSetSecond = makeGetSet('Seconds', false); + + // FORMATTING + + addFormatToken('S', 0, 0, function () { + return ~~(this.millisecond() / 100); + }); + + addFormatToken(0, ['SS', 2], 0, function () { + return ~~(this.millisecond() / 10); + }); + + addFormatToken(0, ['SSS', 3], 0, 'millisecond'); + addFormatToken(0, ['SSSS', 4], 0, function () { + return this.millisecond() * 10; + }); + addFormatToken(0, ['SSSSS', 5], 0, function () { + return this.millisecond() * 100; + }); + addFormatToken(0, ['SSSSSS', 6], 0, function () { + return this.millisecond() * 1000; + }); + addFormatToken(0, ['SSSSSSS', 7], 0, function () { + return this.millisecond() * 10000; + }); + addFormatToken(0, ['SSSSSSSS', 8], 0, function () { + return this.millisecond() * 100000; + }); + addFormatToken(0, ['SSSSSSSSS', 9], 0, function () { + return this.millisecond() * 1000000; + }); + + + // ALIASES + + addUnitAlias('millisecond', 'ms'); + + // PRIORITY + + addUnitPriority('millisecond', 16); + + // PARSING + + addRegexToken('S', match1to3, match1); + addRegexToken('SS', match1to3, match2); + addRegexToken('SSS', match1to3, match3); + + var token; + for (token = 'SSSS'; token.length <= 9; token += 'S') { + addRegexToken(token, matchUnsigned); + } + + function parseMs(input, array) { + array[MILLISECOND] = toInt(('0.' + input) * 1000); + } + + for (token = 'S'; token.length <= 9; token += 'S') { + addParseToken(token, parseMs); + } + // MOMENTS + + var getSetMillisecond = makeGetSet('Milliseconds', false); + + // FORMATTING + + addFormatToken('z', 0, 0, 'zoneAbbr'); + addFormatToken('zz', 0, 0, 'zoneName'); + + // MOMENTS + + function getZoneAbbr () { + return this._isUTC ? 'UTC' : ''; + } + + function getZoneName () { + return this._isUTC ? 'Coordinated Universal Time' : ''; + } + + var momentPrototype__proto = Moment.prototype; + + momentPrototype__proto.add = add_subtract__add; + momentPrototype__proto.calendar = moment_calendar__calendar; + momentPrototype__proto.clone = clone; + momentPrototype__proto.diff = diff; + momentPrototype__proto.endOf = endOf; + momentPrototype__proto.format = moment_format__format; + momentPrototype__proto.from = from; + momentPrototype__proto.fromNow = fromNow; + momentPrototype__proto.to = to; + momentPrototype__proto.toNow = toNow; + momentPrototype__proto.get = stringGet; + momentPrototype__proto.invalidAt = invalidAt; + momentPrototype__proto.isAfter = isAfter; + momentPrototype__proto.isBefore = isBefore; + momentPrototype__proto.isBetween = isBetween; + momentPrototype__proto.isSame = isSame; + momentPrototype__proto.isSameOrAfter = isSameOrAfter; + momentPrototype__proto.isSameOrBefore = isSameOrBefore; + momentPrototype__proto.isValid = moment_valid__isValid; + momentPrototype__proto.lang = lang; + momentPrototype__proto.locale = locale; + momentPrototype__proto.localeData = localeData; + momentPrototype__proto.max = prototypeMax; + momentPrototype__proto.min = prototypeMin; + momentPrototype__proto.parsingFlags = parsingFlags; + momentPrototype__proto.set = stringSet; + momentPrototype__proto.startOf = startOf; + momentPrototype__proto.subtract = add_subtract__subtract; + momentPrototype__proto.toArray = toArray; + momentPrototype__proto.toObject = toObject; + momentPrototype__proto.toDate = toDate; + momentPrototype__proto.toISOString = moment_format__toISOString; + momentPrototype__proto.toJSON = toJSON; + momentPrototype__proto.toString = toString; + momentPrototype__proto.unix = unix; + momentPrototype__proto.valueOf = to_type__valueOf; + momentPrototype__proto.creationData = creationData; + + // Year + momentPrototype__proto.year = getSetYear; + momentPrototype__proto.isLeapYear = getIsLeapYear; + + // Week Year + momentPrototype__proto.weekYear = getSetWeekYear; + momentPrototype__proto.isoWeekYear = getSetISOWeekYear; + + // Quarter + momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter; + + // Month + momentPrototype__proto.month = getSetMonth; + momentPrototype__proto.daysInMonth = getDaysInMonth; + + // Week + momentPrototype__proto.week = momentPrototype__proto.weeks = getSetWeek; + momentPrototype__proto.isoWeek = momentPrototype__proto.isoWeeks = getSetISOWeek; + momentPrototype__proto.weeksInYear = getWeeksInYear; + momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear; + + // Day + momentPrototype__proto.date = getSetDayOfMonth; + momentPrototype__proto.day = momentPrototype__proto.days = getSetDayOfWeek; + momentPrototype__proto.weekday = getSetLocaleDayOfWeek; + momentPrototype__proto.isoWeekday = getSetISODayOfWeek; + momentPrototype__proto.dayOfYear = getSetDayOfYear; + + // Hour + momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour; + + // Minute + momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute; + + // Second + momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond; + + // Millisecond + momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond; + + // Offset + momentPrototype__proto.utcOffset = getSetOffset; + momentPrototype__proto.utc = setOffsetToUTC; + momentPrototype__proto.local = setOffsetToLocal; + momentPrototype__proto.parseZone = setOffsetToParsedOffset; + momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset; + momentPrototype__proto.isDST = isDaylightSavingTime; + momentPrototype__proto.isLocal = isLocal; + momentPrototype__proto.isUtcOffset = isUtcOffset; + momentPrototype__proto.isUtc = isUtc; + momentPrototype__proto.isUTC = isUtc; + + // Timezone + momentPrototype__proto.zoneAbbr = getZoneAbbr; + momentPrototype__proto.zoneName = getZoneName; + + // Deprecations + momentPrototype__proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth); + momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth); + momentPrototype__proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear); + momentPrototype__proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone); + momentPrototype__proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted); + + var momentPrototype = momentPrototype__proto; + + function moment_moment__createUnix (input) { + return local__createLocal(input * 1000); + } + + function moment_moment__createInZone () { + return local__createLocal.apply(null, arguments).parseZone(); + } + + function preParsePostFormat (string) { + return string; + } + + var prototype__proto = Locale.prototype; + + prototype__proto.calendar = locale_calendar__calendar; + prototype__proto.longDateFormat = longDateFormat; + prototype__proto.invalidDate = invalidDate; + prototype__proto.ordinal = ordinal; + prototype__proto.preparse = preParsePostFormat; + prototype__proto.postformat = preParsePostFormat; + prototype__proto.relativeTime = relative__relativeTime; + prototype__proto.pastFuture = pastFuture; + prototype__proto.set = locale_set__set; + + // Month + prototype__proto.months = localeMonths; + prototype__proto.monthsShort = localeMonthsShort; + prototype__proto.monthsParse = localeMonthsParse; + prototype__proto.monthsRegex = monthsRegex; + prototype__proto.monthsShortRegex = monthsShortRegex; + + // Week + prototype__proto.week = localeWeek; + prototype__proto.firstDayOfYear = localeFirstDayOfYear; + prototype__proto.firstDayOfWeek = localeFirstDayOfWeek; + + // Day of Week + prototype__proto.weekdays = localeWeekdays; + prototype__proto.weekdaysMin = localeWeekdaysMin; + prototype__proto.weekdaysShort = localeWeekdaysShort; + prototype__proto.weekdaysParse = localeWeekdaysParse; + + prototype__proto.weekdaysRegex = weekdaysRegex; + prototype__proto.weekdaysShortRegex = weekdaysShortRegex; + prototype__proto.weekdaysMinRegex = weekdaysMinRegex; + + // Hours + prototype__proto.isPM = localeIsPM; + prototype__proto.meridiem = localeMeridiem; + + function lists__get (format, index, field, setter) { + var locale = locale_locales__getLocale(); + var utc = create_utc__createUTC().set(setter, index); + return locale[field](utc, format); + } + + function listMonthsImpl (format, index, field) { + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + + if (index != null) { + return lists__get(format, index, field, 'month'); + } + + var i; + var out = []; + for (i = 0; i < 12; i++) { + out[i] = lists__get(format, i, field, 'month'); + } + return out; + } + + // () + // (5) + // (fmt, 5) + // (fmt) + // (true) + // (true, 5) + // (true, fmt, 5) + // (true, fmt) + function listWeekdaysImpl (localeSorted, format, index, field) { + if (typeof localeSorted === 'boolean') { + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + } else { + format = localeSorted; + index = format; + localeSorted = false; + + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + } + + var locale = locale_locales__getLocale(), + shift = localeSorted ? locale._week.dow : 0; + + if (index != null) { + return lists__get(format, (index + shift) % 7, field, 'day'); + } + + var i; + var out = []; + for (i = 0; i < 7; i++) { + out[i] = lists__get(format, (i + shift) % 7, field, 'day'); + } + return out; + } + + function lists__listMonths (format, index) { + return listMonthsImpl(format, index, 'months'); + } + + function lists__listMonthsShort (format, index) { + return listMonthsImpl(format, index, 'monthsShort'); + } + + function lists__listWeekdays (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdays'); + } + + function lists__listWeekdaysShort (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort'); + } + + function lists__listWeekdaysMin (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin'); + } + + locale_locales__getSetGlobalLocale('en', { + ordinalParse: /\d{1,2}(th|st|nd|rd)/, + ordinal : function (number) { + var b = number % 10, + output = (toInt(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } + }); + + // Side effect imports + utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale); + utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale); + + var mathAbs = Math.abs; + + function duration_abs__abs () { + var data = this._data; + + this._milliseconds = mathAbs(this._milliseconds); + this._days = mathAbs(this._days); + this._months = mathAbs(this._months); + + data.milliseconds = mathAbs(data.milliseconds); + data.seconds = mathAbs(data.seconds); + data.minutes = mathAbs(data.minutes); + data.hours = mathAbs(data.hours); + data.months = mathAbs(data.months); + data.years = mathAbs(data.years); + + return this; + } + + function duration_add_subtract__addSubtract (duration, input, value, direction) { + var other = create__createDuration(input, value); + + duration._milliseconds += direction * other._milliseconds; + duration._days += direction * other._days; + duration._months += direction * other._months; + + return duration._bubble(); + } + + // supports only 2.0-style add(1, 's') or add(duration) + function duration_add_subtract__add (input, value) { + return duration_add_subtract__addSubtract(this, input, value, 1); + } + + // supports only 2.0-style subtract(1, 's') or subtract(duration) + function duration_add_subtract__subtract (input, value) { + return duration_add_subtract__addSubtract(this, input, value, -1); + } + + function absCeil (number) { + if (number < 0) { + return Math.floor(number); + } else { + return Math.ceil(number); + } + } + + function bubble () { + var milliseconds = this._milliseconds; + var days = this._days; + var months = this._months; + var data = this._data; + var seconds, minutes, hours, years, monthsFromDays; + + // if we have a mix of positive and negative values, bubble down first + // check: https://github.com/moment/moment/issues/2166 + if (!((milliseconds >= 0 && days >= 0 && months >= 0) || + (milliseconds <= 0 && days <= 0 && months <= 0))) { + milliseconds += absCeil(monthsToDays(months) + days) * 864e5; + days = 0; + months = 0; + } + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absFloor(milliseconds / 1000); + data.seconds = seconds % 60; + + minutes = absFloor(seconds / 60); + data.minutes = minutes % 60; + + hours = absFloor(minutes / 60); + data.hours = hours % 24; + + days += absFloor(hours / 24); + + // convert days to months + monthsFromDays = absFloor(daysToMonths(days)); + months += monthsFromDays; + days -= absCeil(monthsToDays(monthsFromDays)); + + // 12 months -> 1 year + years = absFloor(months / 12); + months %= 12; + + data.days = days; + data.months = months; + data.years = years; + + return this; + } + + function daysToMonths (days) { + // 400 years have 146097 days (taking into account leap year rules) + // 400 years have 12 months === 4800 + return days * 4800 / 146097; + } + + function monthsToDays (months) { + // the reverse of daysToMonths + return months * 146097 / 4800; + } + + function as (units) { + var days; + var months; + var milliseconds = this._milliseconds; + + units = normalizeUnits(units); + + if (units === 'month' || units === 'year') { + days = this._days + milliseconds / 864e5; + months = this._months + daysToMonths(days); + return units === 'month' ? months : months / 12; + } else { + // handle milliseconds separately because of floating point math errors (issue #1867) + days = this._days + Math.round(monthsToDays(this._months)); + switch (units) { + case 'week' : return days / 7 + milliseconds / 6048e5; + case 'day' : return days + milliseconds / 864e5; + case 'hour' : return days * 24 + milliseconds / 36e5; + case 'minute' : return days * 1440 + milliseconds / 6e4; + case 'second' : return days * 86400 + milliseconds / 1000; + // Math.floor prevents floating point math errors here + case 'millisecond': return Math.floor(days * 864e5) + milliseconds; + default: throw new Error('Unknown unit ' + units); + } + } + } + + // TODO: Use this.as('ms')? + function duration_as__valueOf () { + return ( + this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6 + ); + } + + function makeAs (alias) { + return function () { + return this.as(alias); + }; + } + + var asMilliseconds = makeAs('ms'); + var asSeconds = makeAs('s'); + var asMinutes = makeAs('m'); + var asHours = makeAs('h'); + var asDays = makeAs('d'); + var asWeeks = makeAs('w'); + var asMonths = makeAs('M'); + var asYears = makeAs('y'); + + function duration_get__get (units) { + units = normalizeUnits(units); + return this[units + 's'](); + } + + function makeGetter(name) { + return function () { + return this._data[name]; + }; + } + + var milliseconds = makeGetter('milliseconds'); + var seconds = makeGetter('seconds'); + var minutes = makeGetter('minutes'); + var hours = makeGetter('hours'); + var days = makeGetter('days'); + var duration_get__months = makeGetter('months'); + var years = makeGetter('years'); + + function weeks () { + return absFloor(this.days() / 7); + } + + var round = Math.round; + var thresholds = { + s: 45, // seconds to minute + m: 45, // minutes to hour + h: 22, // hours to day + d: 26, // days to month + M: 11 // months to year + }; + + // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize + function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { + return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); + } + + function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) { + var duration = create__createDuration(posNegDuration).abs(); + var seconds = round(duration.as('s')); + var minutes = round(duration.as('m')); + var hours = round(duration.as('h')); + var days = round(duration.as('d')); + var months = round(duration.as('M')); + var years = round(duration.as('y')); + + var a = seconds < thresholds.s && ['s', seconds] || + minutes <= 1 && ['m'] || + minutes < thresholds.m && ['mm', minutes] || + hours <= 1 && ['h'] || + hours < thresholds.h && ['hh', hours] || + days <= 1 && ['d'] || + days < thresholds.d && ['dd', days] || + months <= 1 && ['M'] || + months < thresholds.M && ['MM', months] || + years <= 1 && ['y'] || ['yy', years]; + + a[2] = withoutSuffix; + a[3] = +posNegDuration > 0; + a[4] = locale; + return substituteTimeAgo.apply(null, a); + } + + // This function allows you to set the rounding function for relative time strings + function duration_humanize__getSetRelativeTimeRounding (roundingFunction) { + if (roundingFunction === undefined) { + return round; + } + if (typeof(roundingFunction) === 'function') { + round = roundingFunction; + return true; + } + return false; + } + + // This function allows you to set a threshold for relative time strings + function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) { + if (thresholds[threshold] === undefined) { + return false; + } + if (limit === undefined) { + return thresholds[threshold]; + } + thresholds[threshold] = limit; + return true; + } + + function humanize (withSuffix) { + var locale = this.localeData(); + var output = duration_humanize__relativeTime(this, !withSuffix, locale); + + if (withSuffix) { + output = locale.pastFuture(+this, output); + } + + return locale.postformat(output); + } + + var iso_string__abs = Math.abs; + + function iso_string__toISOString() { + // for ISO strings we do not use the normal bubbling rules: + // * milliseconds bubble up until they become hours + // * days do not bubble at all + // * months bubble up until they become years + // This is because there is no context-free conversion between hours and days + // (think of clock changes) + // and also not between days and months (28-31 days per month) + var seconds = iso_string__abs(this._milliseconds) / 1000; + var days = iso_string__abs(this._days); + var months = iso_string__abs(this._months); + var minutes, hours, years; + + // 3600 seconds -> 60 minutes -> 1 hour + minutes = absFloor(seconds / 60); + hours = absFloor(minutes / 60); + seconds %= 60; + minutes %= 60; + + // 12 months -> 1 year + years = absFloor(months / 12); + months %= 12; + + + // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js + var Y = years; + var M = months; + var D = days; + var h = hours; + var m = minutes; + var s = seconds; + var total = this.asSeconds(); + + if (!total) { + // this is the same as C#'s (Noda) and python (isodate)... + // but not other JS (goog.date) + return 'P0D'; + } + + return (total < 0 ? '-' : '') + + 'P' + + (Y ? Y + 'Y' : '') + + (M ? M + 'M' : '') + + (D ? D + 'D' : '') + + ((h || m || s) ? 'T' : '') + + (h ? h + 'H' : '') + + (m ? m + 'M' : '') + + (s ? s + 'S' : ''); + } + + var duration_prototype__proto = Duration.prototype; + + duration_prototype__proto.abs = duration_abs__abs; + duration_prototype__proto.add = duration_add_subtract__add; + duration_prototype__proto.subtract = duration_add_subtract__subtract; + duration_prototype__proto.as = as; + duration_prototype__proto.asMilliseconds = asMilliseconds; + duration_prototype__proto.asSeconds = asSeconds; + duration_prototype__proto.asMinutes = asMinutes; + duration_prototype__proto.asHours = asHours; + duration_prototype__proto.asDays = asDays; + duration_prototype__proto.asWeeks = asWeeks; + duration_prototype__proto.asMonths = asMonths; + duration_prototype__proto.asYears = asYears; + duration_prototype__proto.valueOf = duration_as__valueOf; + duration_prototype__proto._bubble = bubble; + duration_prototype__proto.get = duration_get__get; + duration_prototype__proto.milliseconds = milliseconds; + duration_prototype__proto.seconds = seconds; + duration_prototype__proto.minutes = minutes; + duration_prototype__proto.hours = hours; + duration_prototype__proto.days = days; + duration_prototype__proto.weeks = weeks; + duration_prototype__proto.months = duration_get__months; + duration_prototype__proto.years = years; + duration_prototype__proto.humanize = humanize; + duration_prototype__proto.toISOString = iso_string__toISOString; + duration_prototype__proto.toString = iso_string__toISOString; + duration_prototype__proto.toJSON = iso_string__toISOString; + duration_prototype__proto.locale = locale; + duration_prototype__proto.localeData = localeData; + + // Deprecations + duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString); + duration_prototype__proto.lang = lang; + + // Side effect imports + + // FORMATTING + + addFormatToken('X', 0, 0, 'unix'); + addFormatToken('x', 0, 0, 'valueOf'); + + // PARSING + + addRegexToken('x', matchSigned); + addRegexToken('X', matchTimestamp); + addParseToken('X', function (input, array, config) { + config._d = new Date(parseFloat(input, 10) * 1000); + }); + addParseToken('x', function (input, array, config) { + config._d = new Date(toInt(input)); + }); + + // Side effect imports + + ; + + + utils_hooks__hooks.version = '2.14.1'; + + setHookCallback(local__createLocal); + + utils_hooks__hooks.fn = momentPrototype; + utils_hooks__hooks.min = min; + utils_hooks__hooks.max = max; + utils_hooks__hooks.now = now; + utils_hooks__hooks.utc = create_utc__createUTC; + utils_hooks__hooks.unix = moment_moment__createUnix; + utils_hooks__hooks.months = lists__listMonths; + utils_hooks__hooks.isDate = isDate; + utils_hooks__hooks.locale = locale_locales__getSetGlobalLocale; + utils_hooks__hooks.invalid = valid__createInvalid; + utils_hooks__hooks.duration = create__createDuration; + utils_hooks__hooks.isMoment = isMoment; + utils_hooks__hooks.weekdays = lists__listWeekdays; + utils_hooks__hooks.parseZone = moment_moment__createInZone; + utils_hooks__hooks.localeData = locale_locales__getLocale; + utils_hooks__hooks.isDuration = isDuration; + utils_hooks__hooks.monthsShort = lists__listMonthsShort; + utils_hooks__hooks.weekdaysMin = lists__listWeekdaysMin; + utils_hooks__hooks.defineLocale = defineLocale; + utils_hooks__hooks.updateLocale = updateLocale; + utils_hooks__hooks.locales = locale_locales__listLocales; + utils_hooks__hooks.weekdaysShort = lists__listWeekdaysShort; + utils_hooks__hooks.normalizeUnits = normalizeUnits; + utils_hooks__hooks.relativeTimeRounding = duration_humanize__getSetRelativeTimeRounding; + utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold; + utils_hooks__hooks.calendarFormat = getCalendarFormat; + utils_hooks__hooks.prototype = momentPrototype; + + var moment__default = utils_hooks__hooks; + + + var af = moment__default.defineLocale('af', { + months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'), + weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'), + weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'), + meridiemParse: /vm|nm/i, + isPM : function (input) { + return /^nm$/i.test(input); + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower ? 'vm' : 'VM'; + } else { + return isLower ? 'nm' : 'NM'; + } + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Vandag om] LT', + nextDay : '[Môre om] LT', + nextWeek : 'dddd [om] LT', + lastDay : '[Gister om] LT', + lastWeek : '[Laas] dddd [om] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'oor %s', + past : '%s gelede', + s : '\'n paar sekondes', + m : '\'n minuut', + mm : '%d minute', + h : '\'n uur', + hh : '%d ure', + d : '\'n dag', + dd : '%d dae', + M : '\'n maand', + MM : '%d maande', + y : '\'n jaar', + yy : '%d jaar' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter + }, + week : { + dow : 1, // Maandag is die eerste dag van die week. + doy : 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar. + } + }); + + + var ar_ma = moment__default.defineLocale('ar-ma', { + months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[اليوم على الساعة] LT', + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'في %s', + past : 'منذ %s', + s : 'ثوان', + m : 'دقيقة', + mm : '%d دقائق', + h : 'ساعة', + hh : '%d ساعات', + d : 'يوم', + dd : '%d أيام', + M : 'شهر', + MM : '%d أشهر', + y : 'سنة', + yy : '%d سنوات' + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var ar_sa__symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' + }, ar_sa__numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' + }; + + var ar_sa = moment__default.defineLocale('ar-sa', { + months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ص'; + } else { + return 'م'; + } + }, + calendar : { + sameDay: '[اليوم على الساعة] LT', + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'في %s', + past : 'منذ %s', + s : 'ثوان', + m : 'دقيقة', + mm : '%d دقائق', + h : 'ساعة', + hh : '%d ساعات', + d : 'يوم', + dd : '%d أيام', + M : 'شهر', + MM : '%d أشهر', + y : 'سنة', + yy : '%d سنوات' + }, + preparse: function (string) { + return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) { + return ar_sa__numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return ar_sa__symbolMap[match]; + }).replace(/,/g, '،'); + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var ar_tn = moment__default.defineLocale('ar-tn', { + months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[اليوم على الساعة] LT', + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime: { + future: 'في %s', + past: 'منذ %s', + s: 'ثوان', + m: 'دقيقة', + mm: '%d دقائق', + h: 'ساعة', + hh: '%d ساعات', + d: 'يوم', + dd: '%d أيام', + M: 'شهر', + MM: '%d أشهر', + y: 'سنة', + yy: '%d سنوات' + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var ar__symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' + }, ar__numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' + }, pluralForm = function (n) { + return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5; + }, plurals = { + s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'], + m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'], + h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'], + d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'], + M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'], + y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام'] + }, pluralize = function (u) { + return function (number, withoutSuffix, string, isFuture) { + var f = pluralForm(number), + str = plurals[u][pluralForm(number)]; + if (f === 2) { + str = str[withoutSuffix ? 0 : 1]; + } + return str.replace(/%d/i, number); + }; + }, ar__months = [ + 'كانون الثاني يناير', + 'شباط فبراير', + 'آذار مارس', + 'نيسان أبريل', + 'أيار مايو', + 'حزيران يونيو', + 'تموز يوليو', + 'آب أغسطس', + 'أيلول سبتمبر', + 'تشرين الأول أكتوبر', + 'تشرين الثاني نوفمبر', + 'كانون الأول ديسمبر' + ]; + + var ar = moment__default.defineLocale('ar', { + months : ar__months, + monthsShort : ar__months, + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'D/\u200FM/\u200FYYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ص'; + } else { + return 'م'; + } + }, + calendar : { + sameDay: '[اليوم عند الساعة] LT', + nextDay: '[غدًا عند الساعة] LT', + nextWeek: 'dddd [عند الساعة] LT', + lastDay: '[أمس عند الساعة] LT', + lastWeek: 'dddd [عند الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'بعد %s', + past : 'منذ %s', + s : pluralize('s'), + m : pluralize('m'), + mm : pluralize('m'), + h : pluralize('h'), + hh : pluralize('h'), + d : pluralize('d'), + dd : pluralize('d'), + M : pluralize('M'), + MM : pluralize('M'), + y : pluralize('y'), + yy : pluralize('y') + }, + preparse: function (string) { + return string.replace(/\u200f/g, '').replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) { + return ar__numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return ar__symbolMap[match]; + }).replace(/,/g, '،'); + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var az__suffixes = { + 1: '-inci', + 5: '-inci', + 8: '-inci', + 70: '-inci', + 80: '-inci', + 2: '-nci', + 7: '-nci', + 20: '-nci', + 50: '-nci', + 3: '-üncü', + 4: '-üncü', + 100: '-üncü', + 6: '-ncı', + 9: '-uncu', + 10: '-uncu', + 30: '-uncu', + 60: '-ıncı', + 90: '-ıncı' + }; + + var az = moment__default.defineLocale('az', { + months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'), + monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'), + weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'), + weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'), + weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[bugün saat] LT', + nextDay : '[sabah saat] LT', + nextWeek : '[gələn həftə] dddd [saat] LT', + lastDay : '[dünən] LT', + lastWeek : '[keçən həftə] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s sonra', + past : '%s əvvəl', + s : 'birneçə saniyyə', + m : 'bir dəqiqə', + mm : '%d dəqiqə', + h : 'bir saat', + hh : '%d saat', + d : 'bir gün', + dd : '%d gün', + M : 'bir ay', + MM : '%d ay', + y : 'bir il', + yy : '%d il' + }, + meridiemParse: /gecə|səhər|gündüz|axşam/, + isPM : function (input) { + return /^(gündüz|axşam)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'gecə'; + } else if (hour < 12) { + return 'səhər'; + } else if (hour < 17) { + return 'gündüz'; + } else { + return 'axşam'; + } + }, + ordinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/, + ordinal : function (number) { + if (number === 0) { // special case for zero + return number + '-ıncı'; + } + var a = number % 10, + b = number % 100 - a, + c = number >= 100 ? 100 : null; + return number + (az__suffixes[a] || az__suffixes[b] || az__suffixes[c]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + function be__plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); + } + function be__relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін', + 'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін', + 'dd': 'дзень_дні_дзён', + 'MM': 'месяц_месяцы_месяцаў', + 'yy': 'год_гады_гадоў' + }; + if (key === 'm') { + return withoutSuffix ? 'хвіліна' : 'хвіліну'; + } + else if (key === 'h') { + return withoutSuffix ? 'гадзіна' : 'гадзіну'; + } + else { + return number + ' ' + be__plural(format[key], +number); + } + } + + var be = moment__default.defineLocale('be', { + months : { + format: 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_'), + standalone: 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_') + }, + monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'), + weekdays : { + format: 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_'), + standalone: 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'), + isFormat: /\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/ + }, + weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY г.', + LLL : 'D MMMM YYYY г., HH:mm', + LLLL : 'dddd, D MMMM YYYY г., HH:mm' + }, + calendar : { + sameDay: '[Сёння ў] LT', + nextDay: '[Заўтра ў] LT', + lastDay: '[Учора ў] LT', + nextWeek: function () { + return '[У] dddd [ў] LT'; + }, + lastWeek: function () { + switch (this.day()) { + case 0: + case 3: + case 5: + case 6: + return '[У мінулую] dddd [ў] LT'; + case 1: + case 2: + case 4: + return '[У мінулы] dddd [ў] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'праз %s', + past : '%s таму', + s : 'некалькі секунд', + m : be__relativeTimeWithPlural, + mm : be__relativeTimeWithPlural, + h : be__relativeTimeWithPlural, + hh : be__relativeTimeWithPlural, + d : 'дзень', + dd : be__relativeTimeWithPlural, + M : 'месяц', + MM : be__relativeTimeWithPlural, + y : 'год', + yy : be__relativeTimeWithPlural + }, + meridiemParse: /ночы|раніцы|дня|вечара/, + isPM : function (input) { + return /^(дня|вечара)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночы'; + } else if (hour < 12) { + return 'раніцы'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечара'; + } + }, + ordinalParse: /\d{1,2}-(і|ы|га)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + case 'w': + case 'W': + return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : number + '-ы'; + case 'D': + return number + '-га'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var bg = moment__default.defineLocale('bg', { + months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'), + weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'D.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd, D MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[Днес в] LT', + nextDay : '[Утре в] LT', + nextWeek : 'dddd [в] LT', + lastDay : '[Вчера в] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + case 6: + return '[В изминалата] dddd [в] LT'; + case 1: + case 2: + case 4: + case 5: + return '[В изминалия] dddd [в] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'след %s', + past : 'преди %s', + s : 'няколко секунди', + m : 'минута', + mm : '%d минути', + h : 'час', + hh : '%d часа', + d : 'ден', + dd : '%d дни', + M : 'месец', + MM : '%d месеца', + y : 'година', + yy : '%d години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + ordinal : function (number) { + var lastDigit = number % 10, + last2Digits = number % 100; + if (number === 0) { + return number + '-ев'; + } else if (last2Digits === 0) { + return number + '-ен'; + } else if (last2Digits > 10 && last2Digits < 20) { + return number + '-ти'; + } else if (lastDigit === 1) { + return number + '-ви'; + } else if (lastDigit === 2) { + return number + '-ри'; + } else if (lastDigit === 7 || lastDigit === 8) { + return number + '-ми'; + } else { + return number + '-ти'; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var bn__symbolMap = { + '1': '১', + '2': '২', + '3': '৩', + '4': '৪', + '5': '৫', + '6': '৬', + '7': '৭', + '8': '৮', + '9': '৯', + '0': '০' + }, + bn__numberMap = { + '১': '1', + '২': '2', + '৩': '3', + '৪': '4', + '৫': '5', + '৬': '6', + '৭': '7', + '৮': '8', + '৯': '9', + '০': '0' + }; + + var bn = moment__default.defineLocale('bn', { + months : 'জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'), + monthsShort : 'জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্'.split('_'), + weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রবার_শনিবার'.split('_'), + weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্র_শনি'.split('_'), + weekdaysMin : 'রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি'.split('_'), + longDateFormat : { + LT : 'A h:mm সময়', + LTS : 'A h:mm:ss সময়', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm সময়', + LLLL : 'dddd, D MMMM YYYY, A h:mm সময়' + }, + calendar : { + sameDay : '[আজ] LT', + nextDay : '[আগামীকাল] LT', + nextWeek : 'dddd, LT', + lastDay : '[গতকাল] LT', + lastWeek : '[গত] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s পরে', + past : '%s আগে', + s : 'কয়েক সেকেন্ড', + m : 'এক মিনিট', + mm : '%d মিনিট', + h : 'এক ঘন্টা', + hh : '%d ঘন্টা', + d : 'এক দিন', + dd : '%d দিন', + M : 'এক মাস', + MM : '%d মাস', + y : 'এক বছর', + yy : '%d বছর' + }, + preparse: function (string) { + return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) { + return bn__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return bn__symbolMap[match]; + }); + }, + meridiemParse: /রাত|সকাল|দুপুর|বিকাল|রাত/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if ((meridiem === 'রাত' && hour >= 4) || + (meridiem === 'দুপুর' && hour < 5) || + meridiem === 'বিকাল') { + return hour + 12; + } else { + return hour; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'রাত'; + } else if (hour < 10) { + return 'সকাল'; + } else if (hour < 17) { + return 'দুপুর'; + } else if (hour < 20) { + return 'বিকাল'; + } else { + return 'রাত'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var bo__symbolMap = { + '1': '༡', + '2': '༢', + '3': '༣', + '4': '༤', + '5': '༥', + '6': '༦', + '7': '༧', + '8': '༨', + '9': '༩', + '0': '༠' + }, + bo__numberMap = { + '༡': '1', + '༢': '2', + '༣': '3', + '༤': '4', + '༥': '5', + '༦': '6', + '༧': '7', + '༨': '8', + '༩': '9', + '༠': '0' + }; + + var bo = moment__default.defineLocale('bo', { + months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'), + weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + longDateFormat : { + LT : 'A h:mm', + LTS : 'A h:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm', + LLLL : 'dddd, D MMMM YYYY, A h:mm' + }, + calendar : { + sameDay : '[དི་རིང] LT', + nextDay : '[སང་ཉིན] LT', + nextWeek : '[བདུན་ཕྲག་རྗེས་མ], LT', + lastDay : '[ཁ་སང] LT', + lastWeek : '[བདུན་ཕྲག་མཐའ་མ] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ལ་', + past : '%s སྔན་ལ', + s : 'ལམ་སང', + m : 'སྐར་མ་གཅིག', + mm : '%d སྐར་མ', + h : 'ཆུ་ཚོད་གཅིག', + hh : '%d ཆུ་ཚོད', + d : 'ཉིན་གཅིག', + dd : '%d ཉིན་', + M : 'ཟླ་བ་གཅིག', + MM : '%d ཟླ་བ', + y : 'ལོ་གཅིག', + yy : '%d ལོ' + }, + preparse: function (string) { + return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) { + return bo__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return bo__symbolMap[match]; + }); + }, + meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if ((meridiem === 'མཚན་མོ' && hour >= 4) || + (meridiem === 'ཉིན་གུང' && hour < 5) || + meridiem === 'དགོང་དག') { + return hour + 12; + } else { + return hour; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'མཚན་མོ'; + } else if (hour < 10) { + return 'ཞོགས་ཀས'; + } else if (hour < 17) { + return 'ཉིན་གུང'; + } else if (hour < 20) { + return 'དགོང་དག'; + } else { + return 'མཚན་མོ'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + + function relativeTimeWithMutation(number, withoutSuffix, key) { + var format = { + 'mm': 'munutenn', + 'MM': 'miz', + 'dd': 'devezh' + }; + return number + ' ' + mutation(format[key], number); + } + function specialMutationForYears(number) { + switch (lastNumber(number)) { + case 1: + case 3: + case 4: + case 5: + case 9: + return number + ' bloaz'; + default: + return number + ' vloaz'; + } + } + function lastNumber(number) { + if (number > 9) { + return lastNumber(number % 10); + } + return number; + } + function mutation(text, number) { + if (number === 2) { + return softMutation(text); + } + return text; + } + function softMutation(text) { + var mutationTable = { + 'm': 'v', + 'b': 'v', + 'd': 'z' + }; + if (mutationTable[text.charAt(0)] === undefined) { + return text; + } + return mutationTable[text.charAt(0)] + text.substring(1); + } + + var br = moment__default.defineLocale('br', { + months : 'Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split('_'), + monthsShort : 'Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'), + weekdays : 'Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn'.split('_'), + weekdaysShort : 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'), + weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'h[e]mm A', + LTS : 'h[e]mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D [a viz] MMMM YYYY', + LLL : 'D [a viz] MMMM YYYY h[e]mm A', + LLLL : 'dddd, D [a viz] MMMM YYYY h[e]mm A' + }, + calendar : { + sameDay : '[Hiziv da] LT', + nextDay : '[Warc\'hoazh da] LT', + nextWeek : 'dddd [da] LT', + lastDay : '[Dec\'h da] LT', + lastWeek : 'dddd [paset da] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'a-benn %s', + past : '%s \'zo', + s : 'un nebeud segondennoù', + m : 'ur vunutenn', + mm : relativeTimeWithMutation, + h : 'un eur', + hh : '%d eur', + d : 'un devezh', + dd : relativeTimeWithMutation, + M : 'ur miz', + MM : relativeTimeWithMutation, + y : 'ur bloaz', + yy : specialMutationForYears + }, + ordinalParse: /\d{1,2}(añ|vet)/, + ordinal : function (number) { + var output = (number === 1) ? 'añ' : 'vet'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + function bs__translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } + } + + var bs = moment__default.defineLocale('bs', { + months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : bs__translate, + mm : bs__translate, + h : bs__translate, + hh : bs__translate, + d : 'dan', + dd : bs__translate, + M : 'mjesec', + MM : bs__translate, + y : 'godinu', + yy : bs__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var ca = moment__default.defineLocale('ca', { + months : 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'), + monthsShort : 'gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.'.split('_'), + monthsParseExact : true, + weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'), + weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'), + weekdaysMin : 'Dg_Dl_Dt_Dc_Dj_Dv_Ds'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd D MMMM YYYY H:mm' + }, + calendar : { + sameDay : function () { + return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + nextDay : function () { + return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + lastDay : function () { + return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'en %s', + past : 'fa %s', + s : 'uns segons', + m : 'un minut', + mm : '%d minuts', + h : 'una hora', + hh : '%d hores', + d : 'un dia', + dd : '%d dies', + M : 'un mes', + MM : '%d mesos', + y : 'un any', + yy : '%d anys' + }, + ordinalParse: /\d{1,2}(r|n|t|è|a)/, + ordinal : function (number, period) { + var output = (number === 1) ? 'r' : + (number === 2) ? 'n' : + (number === 3) ? 'r' : + (number === 4) ? 't' : 'è'; + if (period === 'w' || period === 'W') { + output = 'a'; + } + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var cs__months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_'), + cs__monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_'); + function cs__plural(n) { + return (n > 1) && (n < 5) && (~~(n / 10) !== 1); + } + function cs__translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': // a few seconds / in a few seconds / a few seconds ago + return (withoutSuffix || isFuture) ? 'pár sekund' : 'pár sekundami'; + case 'm': // a minute / in a minute / a minute ago + return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou'); + case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago + if (withoutSuffix || isFuture) { + return result + (cs__plural(number) ? 'minuty' : 'minut'); + } else { + return result + 'minutami'; + } + break; + case 'h': // an hour / in an hour / an hour ago + return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou'); + case 'hh': // 9 hours / in 9 hours / 9 hours ago + if (withoutSuffix || isFuture) { + return result + (cs__plural(number) ? 'hodiny' : 'hodin'); + } else { + return result + 'hodinami'; + } + break; + case 'd': // a day / in a day / a day ago + return (withoutSuffix || isFuture) ? 'den' : 'dnem'; + case 'dd': // 9 days / in 9 days / 9 days ago + if (withoutSuffix || isFuture) { + return result + (cs__plural(number) ? 'dny' : 'dní'); + } else { + return result + 'dny'; + } + break; + case 'M': // a month / in a month / a month ago + return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem'; + case 'MM': // 9 months / in 9 months / 9 months ago + if (withoutSuffix || isFuture) { + return result + (cs__plural(number) ? 'měsíce' : 'měsíců'); + } else { + return result + 'měsíci'; + } + break; + case 'y': // a year / in a year / a year ago + return (withoutSuffix || isFuture) ? 'rok' : 'rokem'; + case 'yy': // 9 years / in 9 years / 9 years ago + if (withoutSuffix || isFuture) { + return result + (cs__plural(number) ? 'roky' : 'let'); + } else { + return result + 'lety'; + } + break; + } + } + + var cs = moment__default.defineLocale('cs', { + months : cs__months, + monthsShort : cs__monthsShort, + monthsParse : (function (months, monthsShort) { + var i, _monthsParse = []; + for (i = 0; i < 12; i++) { + // use custom parser to solve problem with July (červenec) + _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i'); + } + return _monthsParse; + }(cs__months, cs__monthsShort)), + shortMonthsParse : (function (monthsShort) { + var i, _shortMonthsParse = []; + for (i = 0; i < 12; i++) { + _shortMonthsParse[i] = new RegExp('^' + monthsShort[i] + '$', 'i'); + } + return _shortMonthsParse; + }(cs__monthsShort)), + longMonthsParse : (function (months) { + var i, _longMonthsParse = []; + for (i = 0; i < 12; i++) { + _longMonthsParse[i] = new RegExp('^' + months[i] + '$', 'i'); + } + return _longMonthsParse; + }(cs__months)), + weekdays : 'neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota'.split('_'), + weekdaysShort : 'ne_po_út_st_čt_pá_so'.split('_'), + weekdaysMin : 'ne_po_út_st_čt_pá_so'.split('_'), + longDateFormat : { + LT: 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd D. MMMM YYYY H:mm', + l : 'D. M. YYYY' + }, + calendar : { + sameDay: '[dnes v] LT', + nextDay: '[zítra v] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[v neděli v] LT'; + case 1: + case 2: + return '[v] dddd [v] LT'; + case 3: + return '[ve středu v] LT'; + case 4: + return '[ve čtvrtek v] LT'; + case 5: + return '[v pátek v] LT'; + case 6: + return '[v sobotu v] LT'; + } + }, + lastDay: '[včera v] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[minulou neděli v] LT'; + case 1: + case 2: + return '[minulé] dddd [v] LT'; + case 3: + return '[minulou středu v] LT'; + case 4: + case 5: + return '[minulý] dddd [v] LT'; + case 6: + return '[minulou sobotu v] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'za %s', + past : 'před %s', + s : cs__translate, + m : cs__translate, + mm : cs__translate, + h : cs__translate, + hh : cs__translate, + d : cs__translate, + dd : cs__translate, + M : cs__translate, + MM : cs__translate, + y : cs__translate, + yy : cs__translate + }, + ordinalParse : /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var cv = moment__default.defineLocale('cv', { + months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'), + monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'), + weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'), + weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'), + weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]', + LLL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm', + LLLL : 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm' + }, + calendar : { + sameDay: '[Паян] LT [сехетре]', + nextDay: '[Ыран] LT [сехетре]', + lastDay: '[Ӗнер] LT [сехетре]', + nextWeek: '[Ҫитес] dddd LT [сехетре]', + lastWeek: '[Иртнӗ] dddd LT [сехетре]', + sameElse: 'L' + }, + relativeTime : { + future : function (output) { + var affix = /сехет$/i.exec(output) ? 'рен' : /ҫул$/i.exec(output) ? 'тан' : 'ран'; + return output + affix; + }, + past : '%s каялла', + s : 'пӗр-ик ҫеккунт', + m : 'пӗр минут', + mm : '%d минут', + h : 'пӗр сехет', + hh : '%d сехет', + d : 'пӗр кун', + dd : '%d кун', + M : 'пӗр уйӑх', + MM : '%d уйӑх', + y : 'пӗр ҫул', + yy : '%d ҫул' + }, + ordinalParse: /\d{1,2}-мӗш/, + ordinal : '%d-мӗш', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var cy = moment__default.defineLocale('cy', { + months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'), + monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'), + weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'), + weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'), + weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'), + weekdaysParseExact : true, + // time formats are the same as en-gb + longDateFormat: { + LT: 'HH:mm', + LTS : 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd, D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[Heddiw am] LT', + nextDay: '[Yfory am] LT', + nextWeek: 'dddd [am] LT', + lastDay: '[Ddoe am] LT', + lastWeek: 'dddd [diwethaf am] LT', + sameElse: 'L' + }, + relativeTime: { + future: 'mewn %s', + past: '%s yn ôl', + s: 'ychydig eiliadau', + m: 'munud', + mm: '%d munud', + h: 'awr', + hh: '%d awr', + d: 'diwrnod', + dd: '%d diwrnod', + M: 'mis', + MM: '%d mis', + y: 'blwyddyn', + yy: '%d flynedd' + }, + ordinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/, + // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh + ordinal: function (number) { + var b = number, + output = '', + lookup = [ + '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed + 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed + ]; + if (b > 20) { + if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) { + output = 'fed'; // not 30ain, 70ain or 90ain + } else { + output = 'ain'; + } + } else if (b > 0) { + output = lookup[b]; + } + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var da = moment__default.defineLocale('da', { + months : 'januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december'.split('_'), + monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'), + weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'), + weekdaysShort : 'søn_man_tir_ons_tor_fre_lør'.split('_'), + weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY HH:mm', + LLLL : 'dddd [d.] D. MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[I dag kl.] LT', + nextDay : '[I morgen kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[I går kl.] LT', + lastWeek : '[sidste] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'om %s', + past : '%s siden', + s : 'få sekunder', + m : 'et minut', + mm : '%d minutter', + h : 'en time', + hh : '%d timer', + d : 'en dag', + dd : '%d dage', + M : 'en måned', + MM : '%d måneder', + y : 'et år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + function de_at__processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eine Minute', 'einer Minute'], + 'h': ['eine Stunde', 'einer Stunde'], + 'd': ['ein Tag', 'einem Tag'], + 'dd': [number + ' Tage', number + ' Tagen'], + 'M': ['ein Monat', 'einem Monat'], + 'MM': [number + ' Monate', number + ' Monaten'], + 'y': ['ein Jahr', 'einem Jahr'], + 'yy': [number + ' Jahre', number + ' Jahren'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; + } + + var de_at = moment__default.defineLocale('de-at', { + months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort : 'Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + monthsParseExact : true, + weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'), + weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'), + weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY HH:mm', + LLLL : 'dddd, D. MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + relativeTime : { + future : 'in %s', + past : 'vor %s', + s : 'ein paar Sekunden', + m : de_at__processRelativeTime, + mm : '%d Minuten', + h : de_at__processRelativeTime, + hh : '%d Stunden', + d : de_at__processRelativeTime, + dd : de_at__processRelativeTime, + M : de_at__processRelativeTime, + MM : de_at__processRelativeTime, + y : de_at__processRelativeTime, + yy : de_at__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + function de__processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eine Minute', 'einer Minute'], + 'h': ['eine Stunde', 'einer Stunde'], + 'd': ['ein Tag', 'einem Tag'], + 'dd': [number + ' Tage', number + ' Tagen'], + 'M': ['ein Monat', 'einem Monat'], + 'MM': [number + ' Monate', number + ' Monaten'], + 'y': ['ein Jahr', 'einem Jahr'], + 'yy': [number + ' Jahre', number + ' Jahren'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; + } + + var de = moment__default.defineLocale('de', { + months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort : 'Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + monthsParseExact : true, + weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'), + weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'), + weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY HH:mm', + LLLL : 'dddd, D. MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + relativeTime : { + future : 'in %s', + past : 'vor %s', + s : 'ein paar Sekunden', + m : de__processRelativeTime, + mm : '%d Minuten', + h : de__processRelativeTime, + hh : '%d Stunden', + d : de__processRelativeTime, + dd : de__processRelativeTime, + M : de__processRelativeTime, + MM : de__processRelativeTime, + y : de__processRelativeTime, + yy : de__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var dv__months = [ + 'ޖެނުއަރީ', + 'ފެބްރުއަރީ', + 'މާރިޗު', + 'އޭޕްރީލު', + 'މޭ', + 'ޖޫން', + 'ޖުލައި', + 'އޯގަސްޓު', + 'ސެޕްޓެމްބަރު', + 'އޮކްޓޯބަރު', + 'ނޮވެމްބަރު', + 'ޑިސެމްބަރު' + ], dv__weekdays = [ + 'އާދިއްތަ', + 'ހޯމަ', + 'އަންގާރަ', + 'ބުދަ', + 'ބުރާސްފަތި', + 'ހުކުރު', + 'ހޮނިހިރު' + ]; + + var dv = moment__default.defineLocale('dv', { + months : dv__months, + monthsShort : dv__months, + weekdays : dv__weekdays, + weekdaysShort : dv__weekdays, + weekdaysMin : 'އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި'.split('_'), + longDateFormat : { + + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'D/M/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + meridiemParse: /މކ|މފ/, + isPM : function (input) { + return 'މފ' === input; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'މކ'; + } else { + return 'މފ'; + } + }, + calendar : { + sameDay : '[މިއަދު] LT', + nextDay : '[މާދަމާ] LT', + nextWeek : 'dddd LT', + lastDay : '[އިއްޔެ] LT', + lastWeek : '[ފާއިތުވި] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : 'ތެރޭގައި %s', + past : 'ކުރިން %s', + s : 'ސިކުންތުކޮޅެއް', + m : 'މިނިޓެއް', + mm : 'މިނިޓު %d', + h : 'ގަޑިއިރެއް', + hh : 'ގަޑިއިރު %d', + d : 'ދުވަހެއް', + dd : 'ދުވަސް %d', + M : 'މަހެއް', + MM : 'މަސް %d', + y : 'އަހަރެއް', + yy : 'އަހަރު %d' + }, + preparse: function (string) { + return string.replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/,/g, '،'); + }, + week : { + dow : 7, // Sunday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var el = moment__default.defineLocale('el', { + monthsNominativeEl : 'Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος'.split('_'), + monthsGenitiveEl : 'Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου'.split('_'), + months : function (momentToFormat, format) { + if (/D/.test(format.substring(0, format.indexOf('MMMM')))) { // if there is a day number before 'MMMM' + return this._monthsGenitiveEl[momentToFormat.month()]; + } else { + return this._monthsNominativeEl[momentToFormat.month()]; + } + }, + monthsShort : 'Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ'.split('_'), + weekdays : 'Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο'.split('_'), + weekdaysShort : 'Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ'.split('_'), + weekdaysMin : 'Κυ_Δε_Τρ_Τε_Πε_Πα_Σα'.split('_'), + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'μμ' : 'ΜΜ'; + } else { + return isLower ? 'πμ' : 'ΠΜ'; + } + }, + isPM : function (input) { + return ((input + '').toLowerCase()[0] === 'μ'); + }, + meridiemParse : /[ΠΜ]\.?Μ?\.?/i, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendarEl : { + sameDay : '[Σήμερα {}] LT', + nextDay : '[Αύριο {}] LT', + nextWeek : 'dddd [{}] LT', + lastDay : '[Χθες {}] LT', + lastWeek : function () { + switch (this.day()) { + case 6: + return '[το προηγούμενο] dddd [{}] LT'; + default: + return '[την προηγούμενη] dddd [{}] LT'; + } + }, + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendarEl[key], + hours = mom && mom.hours(); + if (isFunction(output)) { + output = output.apply(mom); + } + return output.replace('{}', (hours % 12 === 1 ? 'στη' : 'στις')); + }, + relativeTime : { + future : 'σε %s', + past : '%s πριν', + s : 'λίγα δευτερόλεπτα', + m : 'ένα λεπτό', + mm : '%d λεπτά', + h : 'μία ώρα', + hh : '%d ώρες', + d : 'μία μέρα', + dd : '%d μέρες', + M : 'ένας μήνας', + MM : '%d μήνες', + y : 'ένας χρόνος', + yy : '%d χρόνια' + }, + ordinalParse: /\d{1,2}η/, + ordinal: '%dη', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4st is the first week of the year. + } + }); + + + var en_au = moment__default.defineLocale('en-au', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var en_ca = moment__default.defineLocale('en-ca', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'YYYY-MM-DD', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY h:mm A', + LLLL : 'dddd, MMMM D, YYYY h:mm A' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } + }); + + + var en_gb = moment__default.defineLocale('en-gb', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var en_ie = moment__default.defineLocale('en-ie', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var en_nz = moment__default.defineLocale('en-nz', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var eo = moment__default.defineLocale('eo', { + months : 'januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro'.split('_'), + monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec'.split('_'), + weekdays : 'Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato'.split('_'), + weekdaysShort : 'Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Ĵa_Ve_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'D[-an de] MMMM, YYYY', + LLL : 'D[-an de] MMMM, YYYY HH:mm', + LLLL : 'dddd, [la] D[-an de] MMMM, YYYY HH:mm' + }, + meridiemParse: /[ap]\.t\.m/i, + isPM: function (input) { + return input.charAt(0).toLowerCase() === 'p'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'p.t.m.' : 'P.T.M.'; + } else { + return isLower ? 'a.t.m.' : 'A.T.M.'; + } + }, + calendar : { + sameDay : '[Hodiaŭ je] LT', + nextDay : '[Morgaŭ je] LT', + nextWeek : 'dddd [je] LT', + lastDay : '[Hieraŭ je] LT', + lastWeek : '[pasinta] dddd [je] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'je %s', + past : 'antaŭ %s', + s : 'sekundoj', + m : 'minuto', + mm : '%d minutoj', + h : 'horo', + hh : '%d horoj', + d : 'tago',//ne 'diurno', ĉar estas uzita por proksimumo + dd : '%d tagoj', + M : 'monato', + MM : '%d monatoj', + y : 'jaro', + yy : '%d jaroj' + }, + ordinalParse: /\d{1,2}a/, + ordinal : '%da', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var es_do__monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_'), + es_do__monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_'); + + var es_do = moment__default.defineLocale('es-do', { + months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return es_do__monthsShort[m.month()]; + } else { + return es_do__monthsShortDot[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'), + weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'), + weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY h:mm A', + LLLL : 'dddd, D [de] MMMM [de] YYYY h:mm A' + }, + calendar : { + sameDay : function () { + return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextDay : function () { + return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastDay : function () { + return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'en %s', + past : 'hace %s', + s : 'unos segundos', + m : 'un minuto', + mm : '%d minutos', + h : 'una hora', + hh : '%d horas', + d : 'un día', + dd : '%d días', + M : 'un mes', + MM : '%d meses', + y : 'un año', + yy : '%d años' + }, + ordinalParse : /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var es__monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_'), + es__monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_'); + + var es = moment__default.defineLocale('es', { + months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return es__monthsShort[m.month()]; + } else { + return es__monthsShortDot[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'), + weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'), + weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY H:mm', + LLLL : 'dddd, D [de] MMMM [de] YYYY H:mm' + }, + calendar : { + sameDay : function () { + return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextDay : function () { + return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastDay : function () { + return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'en %s', + past : 'hace %s', + s : 'unos segundos', + m : 'un minuto', + mm : '%d minutos', + h : 'una hora', + hh : '%d horas', + d : 'un día', + dd : '%d días', + M : 'un mes', + MM : '%d meses', + y : 'un año', + yy : '%d años' + }, + ordinalParse : /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + function et__processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'], + 'm' : ['ühe minuti', 'üks minut'], + 'mm': [number + ' minuti', number + ' minutit'], + 'h' : ['ühe tunni', 'tund aega', 'üks tund'], + 'hh': [number + ' tunni', number + ' tundi'], + 'd' : ['ühe päeva', 'üks päev'], + 'M' : ['kuu aja', 'kuu aega', 'üks kuu'], + 'MM': [number + ' kuu', number + ' kuud'], + 'y' : ['ühe aasta', 'aasta', 'üks aasta'], + 'yy': [number + ' aasta', number + ' aastat'] + }; + if (withoutSuffix) { + return format[key][2] ? format[key][2] : format[key][1]; + } + return isFuture ? format[key][0] : format[key][1]; + } + + var et = moment__default.defineLocale('et', { + months : 'jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember'.split('_'), + monthsShort : 'jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets'.split('_'), + weekdays : 'pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev'.split('_'), + weekdaysShort : 'P_E_T_K_N_R_L'.split('_'), + weekdaysMin : 'P_E_T_K_N_R_L'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[Täna,] LT', + nextDay : '[Homme,] LT', + nextWeek : '[Järgmine] dddd LT', + lastDay : '[Eile,] LT', + lastWeek : '[Eelmine] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s pärast', + past : '%s tagasi', + s : et__processRelativeTime, + m : et__processRelativeTime, + mm : et__processRelativeTime, + h : et__processRelativeTime, + hh : et__processRelativeTime, + d : et__processRelativeTime, + dd : '%d päeva', + M : et__processRelativeTime, + MM : et__processRelativeTime, + y : et__processRelativeTime, + yy : et__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var eu = moment__default.defineLocale('eu', { + months : 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split('_'), + monthsShort : 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split('_'), + monthsParseExact : true, + weekdays : 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split('_'), + weekdaysShort : 'ig._al._ar._az._og._ol._lr.'.split('_'), + weekdaysMin : 'ig_al_ar_az_og_ol_lr'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'YYYY[ko] MMMM[ren] D[a]', + LLL : 'YYYY[ko] MMMM[ren] D[a] HH:mm', + LLLL : 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm', + l : 'YYYY-M-D', + ll : 'YYYY[ko] MMM D[a]', + lll : 'YYYY[ko] MMM D[a] HH:mm', + llll : 'ddd, YYYY[ko] MMM D[a] HH:mm' + }, + calendar : { + sameDay : '[gaur] LT[etan]', + nextDay : '[bihar] LT[etan]', + nextWeek : 'dddd LT[etan]', + lastDay : '[atzo] LT[etan]', + lastWeek : '[aurreko] dddd LT[etan]', + sameElse : 'L' + }, + relativeTime : { + future : '%s barru', + past : 'duela %s', + s : 'segundo batzuk', + m : 'minutu bat', + mm : '%d minutu', + h : 'ordu bat', + hh : '%d ordu', + d : 'egun bat', + dd : '%d egun', + M : 'hilabete bat', + MM : '%d hilabete', + y : 'urte bat', + yy : '%d urte' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var fa__symbolMap = { + '1': '۱', + '2': '۲', + '3': '۳', + '4': '۴', + '5': '۵', + '6': '۶', + '7': '۷', + '8': '۸', + '9': '۹', + '0': '۰' + }, fa__numberMap = { + '۱': '1', + '۲': '2', + '۳': '3', + '۴': '4', + '۵': '5', + '۶': '6', + '۷': '7', + '۸': '8', + '۹': '9', + '۰': '0' + }; + + var fa = moment__default.defineLocale('fa', { + months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + meridiemParse: /قبل از ظهر|بعد از ظهر/, + isPM: function (input) { + return /بعد از ظهر/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'قبل از ظهر'; + } else { + return 'بعد از ظهر'; + } + }, + calendar : { + sameDay : '[امروز ساعت] LT', + nextDay : '[فردا ساعت] LT', + nextWeek : 'dddd [ساعت] LT', + lastDay : '[دیروز ساعت] LT', + lastWeek : 'dddd [پیش] [ساعت] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'در %s', + past : '%s پیش', + s : 'چندین ثانیه', + m : 'یک دقیقه', + mm : '%d دقیقه', + h : 'یک ساعت', + hh : '%d ساعت', + d : 'یک روز', + dd : '%d روز', + M : 'یک ماه', + MM : '%d ماه', + y : 'یک سال', + yy : '%d سال' + }, + preparse: function (string) { + return string.replace(/[۰-۹]/g, function (match) { + return fa__numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return fa__symbolMap[match]; + }).replace(/,/g, '،'); + }, + ordinalParse: /\d{1,2}م/, + ordinal : '%dم', + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '), + numbersFuture = [ + 'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden', + numbersPast[7], numbersPast[8], numbersPast[9] + ]; + function fi__translate(number, withoutSuffix, key, isFuture) { + var result = ''; + switch (key) { + case 's': + return isFuture ? 'muutaman sekunnin' : 'muutama sekunti'; + case 'm': + return isFuture ? 'minuutin' : 'minuutti'; + case 'mm': + result = isFuture ? 'minuutin' : 'minuuttia'; + break; + case 'h': + return isFuture ? 'tunnin' : 'tunti'; + case 'hh': + result = isFuture ? 'tunnin' : 'tuntia'; + break; + case 'd': + return isFuture ? 'päivän' : 'päivä'; + case 'dd': + result = isFuture ? 'päivän' : 'päivää'; + break; + case 'M': + return isFuture ? 'kuukauden' : 'kuukausi'; + case 'MM': + result = isFuture ? 'kuukauden' : 'kuukautta'; + break; + case 'y': + return isFuture ? 'vuoden' : 'vuosi'; + case 'yy': + result = isFuture ? 'vuoden' : 'vuotta'; + break; + } + result = verbalNumber(number, isFuture) + ' ' + result; + return result; + } + function verbalNumber(number, isFuture) { + return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number; + } + + var fi = moment__default.defineLocale('fi', { + months : 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split('_'), + monthsShort : 'tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu'.split('_'), + weekdays : 'sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai'.split('_'), + weekdaysShort : 'su_ma_ti_ke_to_pe_la'.split('_'), + weekdaysMin : 'su_ma_ti_ke_to_pe_la'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD.MM.YYYY', + LL : 'Do MMMM[ta] YYYY', + LLL : 'Do MMMM[ta] YYYY, [klo] HH.mm', + LLLL : 'dddd, Do MMMM[ta] YYYY, [klo] HH.mm', + l : 'D.M.YYYY', + ll : 'Do MMM YYYY', + lll : 'Do MMM YYYY, [klo] HH.mm', + llll : 'ddd, Do MMM YYYY, [klo] HH.mm' + }, + calendar : { + sameDay : '[tänään] [klo] LT', + nextDay : '[huomenna] [klo] LT', + nextWeek : 'dddd [klo] LT', + lastDay : '[eilen] [klo] LT', + lastWeek : '[viime] dddd[na] [klo] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s päästä', + past : '%s sitten', + s : fi__translate, + m : fi__translate, + mm : fi__translate, + h : fi__translate, + hh : fi__translate, + d : fi__translate, + dd : fi__translate, + M : fi__translate, + MM : fi__translate, + y : fi__translate, + yy : fi__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var fo = moment__default.defineLocale('fo', { + months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), + weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'), + weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'), + weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D. MMMM, YYYY HH:mm' + }, + calendar : { + sameDay : '[Í dag kl.] LT', + nextDay : '[Í morgin kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[Í gjár kl.] LT', + lastWeek : '[síðstu] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'um %s', + past : '%s síðani', + s : 'fá sekund', + m : 'ein minutt', + mm : '%d minuttir', + h : 'ein tími', + hh : '%d tímar', + d : 'ein dagur', + dd : '%d dagar', + M : 'ein mánaði', + MM : '%d mánaðir', + y : 'eitt ár', + yy : '%d ár' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var fr_ca = moment__default.defineLocale('fr-ca', { + months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), + monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), + monthsParseExact : true, + weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), + weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Aujourd\'hui à] LT', + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dans %s', + past : 'il y a %s', + s : 'quelques secondes', + m : 'une minute', + mm : '%d minutes', + h : 'une heure', + hh : '%d heures', + d : 'un jour', + dd : '%d jours', + M : 'un mois', + MM : '%d mois', + y : 'un an', + yy : '%d ans' + }, + ordinalParse: /\d{1,2}(er|e)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : 'e'); + } + }); + + + var fr_ch = moment__default.defineLocale('fr-ch', { + months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), + monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), + monthsParseExact : true, + weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), + weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Aujourd\'hui à] LT', + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dans %s', + past : 'il y a %s', + s : 'quelques secondes', + m : 'une minute', + mm : '%d minutes', + h : 'une heure', + hh : '%d heures', + d : 'un jour', + dd : '%d jours', + M : 'un mois', + MM : '%d mois', + y : 'un an', + yy : '%d ans' + }, + ordinalParse: /\d{1,2}(er|e)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : 'e'); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var fr = moment__default.defineLocale('fr', { + months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), + monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), + monthsParseExact : true, + weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), + weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Aujourd\'hui à] LT', + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dans %s', + past : 'il y a %s', + s : 'quelques secondes', + m : 'une minute', + mm : '%d minutes', + h : 'une heure', + hh : '%d heures', + d : 'un jour', + dd : '%d jours', + M : 'un mois', + MM : '%d mois', + y : 'un an', + yy : '%d ans' + }, + ordinalParse: /\d{1,2}(er|)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : ''); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var fy__monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_'), + fy__monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'); + + var fy = moment__default.defineLocale('fy', { + months : 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return fy__monthsShortWithoutDots[m.month()]; + } else { + return fy__monthsShortWithDots[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split('_'), + weekdaysShort : 'si._mo._ti._wo._to._fr._so.'.split('_'), + weekdaysMin : 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[hjoed om] LT', + nextDay: '[moarn om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[juster om] LT', + lastWeek: '[ôfrûne] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'oer %s', + past : '%s lyn', + s : 'in pear sekonden', + m : 'ien minút', + mm : '%d minuten', + h : 'ien oere', + hh : '%d oeren', + d : 'ien dei', + dd : '%d dagen', + M : 'ien moanne', + MM : '%d moannen', + y : 'ien jier', + yy : '%d jierren' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var gd__months = [ + 'Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean', 'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal', 'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd' + ]; + + var gd__monthsShort = ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh']; + + var gd__weekdays = ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne']; + + var weekdaysShort = ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis']; + + var weekdaysMin = ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa']; + + var gd = moment__default.defineLocale('gd', { + months : gd__months, + monthsShort : gd__monthsShort, + monthsParseExact : true, + weekdays : gd__weekdays, + weekdaysShort : weekdaysShort, + weekdaysMin : weekdaysMin, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[An-diugh aig] LT', + nextDay : '[A-màireach aig] LT', + nextWeek : 'dddd [aig] LT', + lastDay : '[An-dè aig] LT', + lastWeek : 'dddd [seo chaidh] [aig] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'ann an %s', + past : 'bho chionn %s', + s : 'beagan diogan', + m : 'mionaid', + mm : '%d mionaidean', + h : 'uair', + hh : '%d uairean', + d : 'latha', + dd : '%d latha', + M : 'mìos', + MM : '%d mìosan', + y : 'bliadhna', + yy : '%d bliadhna' + }, + ordinalParse : /\d{1,2}(d|na|mh)/, + ordinal : function (number) { + var output = number === 1 ? 'd' : number % 10 === 2 ? 'na' : 'mh'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var gl = moment__default.defineLocale('gl', { + months : 'Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro'.split('_'), + monthsShort : 'Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.'.split('_'), + monthsParseExact: true, + weekdays : 'Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado'.split('_'), + weekdaysShort : 'Dom._Lun._Mar._Mér._Xov._Ven._Sáb.'.split('_'), + weekdaysMin : 'Do_Lu_Ma_Mé_Xo_Ve_Sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd D MMMM YYYY H:mm' + }, + calendar : { + sameDay : function () { + return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; + }, + nextDay : function () { + return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; + }, + nextWeek : function () { + return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + lastDay : function () { + return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT'; + }, + lastWeek : function () { + return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : function (str) { + if (str === 'uns segundos') { + return 'nuns segundos'; + } + return 'en ' + str; + }, + past : 'hai %s', + s : 'uns segundos', + m : 'un minuto', + mm : '%d minutos', + h : 'unha hora', + hh : '%d horas', + d : 'un día', + dd : '%d días', + M : 'un mes', + MM : '%d meses', + y : 'un ano', + yy : '%d anos' + }, + ordinalParse : /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var he = moment__default.defineLocale('he', { + months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'), + monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'), + weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'), + weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'), + weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [ב]MMMM YYYY', + LLL : 'D [ב]MMMM YYYY HH:mm', + LLLL : 'dddd, D [ב]MMMM YYYY HH:mm', + l : 'D/M/YYYY', + ll : 'D MMM YYYY', + lll : 'D MMM YYYY HH:mm', + llll : 'ddd, D MMM YYYY HH:mm' + }, + calendar : { + sameDay : '[היום ב־]LT', + nextDay : '[מחר ב־]LT', + nextWeek : 'dddd [בשעה] LT', + lastDay : '[אתמול ב־]LT', + lastWeek : '[ביום] dddd [האחרון בשעה] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'בעוד %s', + past : 'לפני %s', + s : 'מספר שניות', + m : 'דקה', + mm : '%d דקות', + h : 'שעה', + hh : function (number) { + if (number === 2) { + return 'שעתיים'; + } + return number + ' שעות'; + }, + d : 'יום', + dd : function (number) { + if (number === 2) { + return 'יומיים'; + } + return number + ' ימים'; + }, + M : 'חודש', + MM : function (number) { + if (number === 2) { + return 'חודשיים'; + } + return number + ' חודשים'; + }, + y : 'שנה', + yy : function (number) { + if (number === 2) { + return 'שנתיים'; + } else if (number % 10 === 0 && number !== 10) { + return number + ' שנה'; + } + return number + ' שנים'; + } + }, + meridiemParse: /אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i, + isPM : function (input) { + return /^(אחה"צ|אחרי הצהריים|בערב)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 5) { + return 'לפנות בוקר'; + } else if (hour < 10) { + return 'בבוקר'; + } else if (hour < 12) { + return isLower ? 'לפנה"צ' : 'לפני הצהריים'; + } else if (hour < 18) { + return isLower ? 'אחה"צ' : 'אחרי הצהריים'; + } else { + return 'בערב'; + } + } + }); + + + var hi__symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + hi__numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var hi = moment__default.defineLocale('hi', { + months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'), + monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'), + monthsParseExact: true, + weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm बजे', + LTS : 'A h:mm:ss बजे', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm बजे', + LLLL : 'dddd, D MMMM YYYY, A h:mm बजे' + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[कल] LT', + nextWeek : 'dddd, LT', + lastDay : '[कल] LT', + lastWeek : '[पिछले] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s में', + past : '%s पहले', + s : 'कुछ ही क्षण', + m : 'एक मिनट', + mm : '%d मिनट', + h : 'एक घंटा', + hh : '%d घंटे', + d : 'एक दिन', + dd : '%d दिन', + M : 'एक महीने', + MM : '%d महीने', + y : 'एक वर्ष', + yy : '%d वर्ष' + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return hi__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return hi__symbolMap[match]; + }); + }, + // Hindi notation for meridiems are quite fuzzy in practice. While there exists + // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi. + meridiemParse: /रात|सुबह|दोपहर|शाम/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सुबह') { + return hour; + } else if (meridiem === 'दोपहर') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'शाम') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'रात'; + } else if (hour < 10) { + return 'सुबह'; + } else if (hour < 17) { + return 'दोपहर'; + } else if (hour < 20) { + return 'शाम'; + } else { + return 'रात'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + + function hr__translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } + } + + var hr = moment__default.defineLocale('hr', { + months : { + format: 'siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca'.split('_'), + standalone: 'siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_') + }, + monthsShort : 'sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'), + monthsParseExact: true, + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : hr__translate, + mm : hr__translate, + h : hr__translate, + hh : hr__translate, + d : 'dan', + dd : hr__translate, + M : 'mjesec', + MM : hr__translate, + y : 'godinu', + yy : hr__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' '); + function hu__translate(number, withoutSuffix, key, isFuture) { + var num = number, + suffix; + switch (key) { + case 's': + return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce'; + case 'm': + return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce'); + case 'mm': + return num + (isFuture || withoutSuffix ? ' perc' : ' perce'); + case 'h': + return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája'); + case 'hh': + return num + (isFuture || withoutSuffix ? ' óra' : ' órája'); + case 'd': + return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja'); + case 'dd': + return num + (isFuture || withoutSuffix ? ' nap' : ' napja'); + case 'M': + return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); + case 'MM': + return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); + case 'y': + return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve'); + case 'yy': + return num + (isFuture || withoutSuffix ? ' év' : ' éve'); + } + return ''; + } + function week(isFuture) { + return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]'; + } + + var hu = moment__default.defineLocale('hu', { + months : 'január_február_március_április_május_június_július_augusztus_szeptember_október_november_december'.split('_'), + monthsShort : 'jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec'.split('_'), + weekdays : 'vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat'.split('_'), + weekdaysShort : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'), + weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'YYYY.MM.DD.', + LL : 'YYYY. MMMM D.', + LLL : 'YYYY. MMMM D. H:mm', + LLLL : 'YYYY. MMMM D., dddd H:mm' + }, + meridiemParse: /de|du/i, + isPM: function (input) { + return input.charAt(1).toLowerCase() === 'u'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower === true ? 'de' : 'DE'; + } else { + return isLower === true ? 'du' : 'DU'; + } + }, + calendar : { + sameDay : '[ma] LT[-kor]', + nextDay : '[holnap] LT[-kor]', + nextWeek : function () { + return week.call(this, true); + }, + lastDay : '[tegnap] LT[-kor]', + lastWeek : function () { + return week.call(this, false); + }, + sameElse : 'L' + }, + relativeTime : { + future : '%s múlva', + past : '%s', + s : hu__translate, + m : hu__translate, + mm : hu__translate, + h : hu__translate, + hh : hu__translate, + d : hu__translate, + dd : hu__translate, + M : hu__translate, + MM : hu__translate, + y : hu__translate, + yy : hu__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var hy_am = moment__default.defineLocale('hy-am', { + months : { + format: 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_'), + standalone: 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_') + }, + monthsShort : 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'), + weekdays : 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_'), + weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY թ.', + LLL : 'D MMMM YYYY թ., HH:mm', + LLLL : 'dddd, D MMMM YYYY թ., HH:mm' + }, + calendar : { + sameDay: '[այսօր] LT', + nextDay: '[վաղը] LT', + lastDay: '[երեկ] LT', + nextWeek: function () { + return 'dddd [օրը ժամը] LT'; + }, + lastWeek: function () { + return '[անցած] dddd [օրը ժամը] LT'; + }, + sameElse: 'L' + }, + relativeTime : { + future : '%s հետո', + past : '%s առաջ', + s : 'մի քանի վայրկյան', + m : 'րոպե', + mm : '%d րոպե', + h : 'ժամ', + hh : '%d ժամ', + d : 'օր', + dd : '%d օր', + M : 'ամիս', + MM : '%d ամիս', + y : 'տարի', + yy : '%d տարի' + }, + meridiemParse: /գիշերվա|առավոտվա|ցերեկվա|երեկոյան/, + isPM: function (input) { + return /^(ցերեկվա|երեկոյան)$/.test(input); + }, + meridiem : function (hour) { + if (hour < 4) { + return 'գիշերվա'; + } else if (hour < 12) { + return 'առավոտվա'; + } else if (hour < 17) { + return 'ցերեկվա'; + } else { + return 'երեկոյան'; + } + }, + ordinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/, + ordinal: function (number, period) { + switch (period) { + case 'DDD': + case 'w': + case 'W': + case 'DDDo': + if (number === 1) { + return number + '-ին'; + } + return number + '-րդ'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var id = moment__default.defineLocale('id', { + months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu'.split('_'), + weekdaysShort : 'Min_Sen_Sel_Rab_Kam_Jum_Sab'.split('_'), + weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sb'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /pagi|siang|sore|malam/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'siang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sore' || meridiem === 'malam') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'siang'; + } else if (hours < 19) { + return 'sore'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Besok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kemarin pukul] LT', + lastWeek : 'dddd [lalu pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'dalam %s', + past : '%s yang lalu', + s : 'beberapa detik', + m : 'semenit', + mm : '%d menit', + h : 'sejam', + hh : '%d jam', + d : 'sehari', + dd : '%d hari', + M : 'sebulan', + MM : '%d bulan', + y : 'setahun', + yy : '%d tahun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + function is__plural(n) { + if (n % 100 === 11) { + return true; + } else if (n % 10 === 1) { + return false; + } + return true; + } + function is__translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum'; + case 'm': + return withoutSuffix ? 'mínúta' : 'mínútu'; + case 'mm': + if (is__plural(number)) { + return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum'); + } else if (withoutSuffix) { + return result + 'mínúta'; + } + return result + 'mínútu'; + case 'hh': + if (is__plural(number)) { + return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum'); + } + return result + 'klukkustund'; + case 'd': + if (withoutSuffix) { + return 'dagur'; + } + return isFuture ? 'dag' : 'degi'; + case 'dd': + if (is__plural(number)) { + if (withoutSuffix) { + return result + 'dagar'; + } + return result + (isFuture ? 'daga' : 'dögum'); + } else if (withoutSuffix) { + return result + 'dagur'; + } + return result + (isFuture ? 'dag' : 'degi'); + case 'M': + if (withoutSuffix) { + return 'mánuður'; + } + return isFuture ? 'mánuð' : 'mánuði'; + case 'MM': + if (is__plural(number)) { + if (withoutSuffix) { + return result + 'mánuðir'; + } + return result + (isFuture ? 'mánuði' : 'mánuðum'); + } else if (withoutSuffix) { + return result + 'mánuður'; + } + return result + (isFuture ? 'mánuð' : 'mánuði'); + case 'y': + return withoutSuffix || isFuture ? 'ár' : 'ári'; + case 'yy': + if (is__plural(number)) { + return result + (withoutSuffix || isFuture ? 'ár' : 'árum'); + } + return result + (withoutSuffix || isFuture ? 'ár' : 'ári'); + } + } + + var is = moment__default.defineLocale('is', { + months : 'janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des'.split('_'), + weekdays : 'sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur'.split('_'), + weekdaysShort : 'sun_mán_þri_mið_fim_fös_lau'.split('_'), + weekdaysMin : 'Su_Má_Þr_Mi_Fi_Fö_La'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] H:mm', + LLLL : 'dddd, D. MMMM YYYY [kl.] H:mm' + }, + calendar : { + sameDay : '[í dag kl.] LT', + nextDay : '[á morgun kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[í gær kl.] LT', + lastWeek : '[síðasta] dddd [kl.] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'eftir %s', + past : 'fyrir %s síðan', + s : is__translate, + m : is__translate, + mm : is__translate, + h : 'klukkustund', + hh : is__translate, + d : is__translate, + dd : is__translate, + M : is__translate, + MM : is__translate, + y : is__translate, + yy : is__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var it = moment__default.defineLocale('it', { + months : 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split('_'), + monthsShort : 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'), + weekdays : 'Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato'.split('_'), + weekdaysShort : 'Dom_Lun_Mar_Mer_Gio_Ven_Sab'.split('_'), + weekdaysMin : 'Do_Lu_Ma_Me_Gi_Ve_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Oggi alle] LT', + nextDay: '[Domani alle] LT', + nextWeek: 'dddd [alle] LT', + lastDay: '[Ieri alle] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[la scorsa] dddd [alle] LT'; + default: + return '[lo scorso] dddd [alle] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : function (s) { + return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s; + }, + past : '%s fa', + s : 'alcuni secondi', + m : 'un minuto', + mm : '%d minuti', + h : 'un\'ora', + hh : '%d ore', + d : 'un giorno', + dd : '%d giorni', + M : 'un mese', + MM : '%d mesi', + y : 'un anno', + yy : '%d anni' + }, + ordinalParse : /\d{1,2}º/, + ordinal: '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var ja = moment__default.defineLocale('ja', { + months : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + weekdays : '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'), + weekdaysShort : '日_月_火_水_木_金_土'.split('_'), + weekdaysMin : '日_月_火_水_木_金_土'.split('_'), + longDateFormat : { + LT : 'Ah時m分', + LTS : 'Ah時m分s秒', + L : 'YYYY/MM/DD', + LL : 'YYYY年M月D日', + LLL : 'YYYY年M月D日Ah時m分', + LLLL : 'YYYY年M月D日Ah時m分 dddd' + }, + meridiemParse: /午前|午後/i, + isPM : function (input) { + return input === '午後'; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return '午前'; + } else { + return '午後'; + } + }, + calendar : { + sameDay : '[今日] LT', + nextDay : '[明日] LT', + nextWeek : '[来週]dddd LT', + lastDay : '[昨日] LT', + lastWeek : '[前週]dddd LT', + sameElse : 'L' + }, + ordinalParse : /\d{1,2}日/, + ordinal : function (number, period) { + switch (period) { + case 'd': + case 'D': + case 'DDD': + return number + '日'; + default: + return number; + } + }, + relativeTime : { + future : '%s後', + past : '%s前', + s : '数秒', + m : '1分', + mm : '%d分', + h : '1時間', + hh : '%d時間', + d : '1日', + dd : '%d日', + M : '1ヶ月', + MM : '%dヶ月', + y : '1年', + yy : '%d年' + } + }); + + + var jv = moment__default.defineLocale('jv', { + months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des'.split('_'), + weekdays : 'Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu'.split('_'), + weekdaysShort : 'Min_Sen_Sel_Reb_Kem_Jem_Sep'.split('_'), + weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sp'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /enjing|siyang|sonten|ndalu/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'enjing') { + return hour; + } else if (meridiem === 'siyang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sonten' || meridiem === 'ndalu') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'enjing'; + } else if (hours < 15) { + return 'siyang'; + } else if (hours < 19) { + return 'sonten'; + } else { + return 'ndalu'; + } + }, + calendar : { + sameDay : '[Dinten puniko pukul] LT', + nextDay : '[Mbenjang pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kala wingi pukul] LT', + lastWeek : 'dddd [kepengker pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'wonten ing %s', + past : '%s ingkang kepengker', + s : 'sawetawis detik', + m : 'setunggal menit', + mm : '%d menit', + h : 'setunggal jam', + hh : '%d jam', + d : 'sedinten', + dd : '%d dinten', + M : 'sewulan', + MM : '%d wulan', + y : 'setaun', + yy : '%d taun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var ka = moment__default.defineLocale('ka', { + months : { + standalone: 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'), + format: 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_') + }, + monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'), + weekdays : { + standalone: 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'), + format: 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_'), + isFormat: /(წინა|შემდეგ)/ + }, + weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'), + weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[დღეს] LT[-ზე]', + nextDay : '[ხვალ] LT[-ზე]', + lastDay : '[გუშინ] LT[-ზე]', + nextWeek : '[შემდეგ] dddd LT[-ზე]', + lastWeek : '[წინა] dddd LT-ზე', + sameElse : 'L' + }, + relativeTime : { + future : function (s) { + return (/(წამი|წუთი|საათი|წელი)/).test(s) ? + s.replace(/ი$/, 'ში') : + s + 'ში'; + }, + past : function (s) { + if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) { + return s.replace(/(ი|ე)$/, 'ის წინ'); + } + if ((/წელი/).test(s)) { + return s.replace(/წელი$/, 'წლის წინ'); + } + }, + s : 'რამდენიმე წამი', + m : 'წუთი', + mm : '%d წუთი', + h : 'საათი', + hh : '%d საათი', + d : 'დღე', + dd : '%d დღე', + M : 'თვე', + MM : '%d თვე', + y : 'წელი', + yy : '%d წელი' + }, + ordinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/, + ordinal : function (number) { + if (number === 0) { + return number; + } + if (number === 1) { + return number + '-ლი'; + } + if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) { + return 'მე-' + number; + } + return number + '-ე'; + }, + week : { + dow : 1, + doy : 7 + } + }); + + + var kk__suffixes = { + 0: '-ші', + 1: '-ші', + 2: '-ші', + 3: '-ші', + 4: '-ші', + 5: '-ші', + 6: '-шы', + 7: '-ші', + 8: '-ші', + 9: '-шы', + 10: '-шы', + 20: '-шы', + 30: '-шы', + 40: '-шы', + 50: '-ші', + 60: '-шы', + 70: '-ші', + 80: '-ші', + 90: '-шы', + 100: '-ші' + }; + + var kk = moment__default.defineLocale('kk', { + months : 'қаңтар_ақпан_наурыз_сәуір_мамыр_маусым_шілде_тамыз_қыркүйек_қазан_қараша_желтоқсан'.split('_'), + monthsShort : 'қаң_ақп_нау_сәу_мам_мау_шіл_там_қыр_қаз_қар_жел'.split('_'), + weekdays : 'жексенбі_дүйсенбі_сейсенбі_сәрсенбі_бейсенбі_жұма_сенбі'.split('_'), + weekdaysShort : 'жек_дүй_сей_сәр_бей_жұм_сен'.split('_'), + weekdaysMin : 'жк_дй_сй_ср_бй_жм_сн'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Бүгін сағат] LT', + nextDay : '[Ертең сағат] LT', + nextWeek : 'dddd [сағат] LT', + lastDay : '[Кеше сағат] LT', + lastWeek : '[Өткен аптаның] dddd [сағат] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ішінде', + past : '%s бұрын', + s : 'бірнеше секунд', + m : 'бір минут', + mm : '%d минут', + h : 'бір сағат', + hh : '%d сағат', + d : 'бір күн', + dd : '%d күн', + M : 'бір ай', + MM : '%d ай', + y : 'бір жыл', + yy : '%d жыл' + }, + ordinalParse: /\d{1,2}-(ші|шы)/, + ordinal : function (number) { + var a = number % 10, + b = number >= 100 ? 100 : null; + return number + (kk__suffixes[number] || kk__suffixes[a] || kk__suffixes[b]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var km = moment__default.defineLocale('km', { + months: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + monthsShort: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + longDateFormat: { + LT: 'HH:mm', + LTS : 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd, D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[ថ្ងៃនេះ ម៉ោង] LT', + nextDay: '[ស្អែក ម៉ោង] LT', + nextWeek: 'dddd [ម៉ោង] LT', + lastDay: '[ម្សិលមិញ ម៉ោង] LT', + lastWeek: 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT', + sameElse: 'L' + }, + relativeTime: { + future: '%sទៀត', + past: '%sមុន', + s: 'ប៉ុន្មានវិនាទី', + m: 'មួយនាទី', + mm: '%d នាទី', + h: 'មួយម៉ោង', + hh: '%d ម៉ោង', + d: 'មួយថ្ងៃ', + dd: '%d ថ្ងៃ', + M: 'មួយខែ', + MM: '%d ខែ', + y: 'មួយឆ្នាំ', + yy: '%d ឆ្នាំ' + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var ko = moment__default.defineLocale('ko', { + months : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'), + monthsShort : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'), + weekdays : '일요일_월요일_화요일_수요일_목요일_금요일_토요일'.split('_'), + weekdaysShort : '일_월_화_수_목_금_토'.split('_'), + weekdaysMin : '일_월_화_수_목_금_토'.split('_'), + longDateFormat : { + LT : 'A h시 m분', + LTS : 'A h시 m분 s초', + L : 'YYYY.MM.DD', + LL : 'YYYY년 MMMM D일', + LLL : 'YYYY년 MMMM D일 A h시 m분', + LLLL : 'YYYY년 MMMM D일 dddd A h시 m분' + }, + calendar : { + sameDay : '오늘 LT', + nextDay : '내일 LT', + nextWeek : 'dddd LT', + lastDay : '어제 LT', + lastWeek : '지난주 dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s 후', + past : '%s 전', + s : '몇 초', + ss : '%d초', + m : '일분', + mm : '%d분', + h : '한 시간', + hh : '%d시간', + d : '하루', + dd : '%d일', + M : '한 달', + MM : '%d달', + y : '일 년', + yy : '%d년' + }, + ordinalParse : /\d{1,2}일/, + ordinal : '%d일', + meridiemParse : /오전|오후/, + isPM : function (token) { + return token === '오후'; + }, + meridiem : function (hour, minute, isUpper) { + return hour < 12 ? '오전' : '오후'; + } + }); + + + + var ky__suffixes = { + 0: '-чү', + 1: '-чи', + 2: '-чи', + 3: '-чү', + 4: '-чү', + 5: '-чи', + 6: '-чы', + 7: '-чи', + 8: '-чи', + 9: '-чу', + 10: '-чу', + 20: '-чы', + 30: '-чу', + 40: '-чы', + 50: '-чү', + 60: '-чы', + 70: '-чи', + 80: '-чи', + 90: '-чу', + 100: '-чү' + }; + + var ky = moment__default.defineLocale('ky', { + months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + monthsShort : 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'), + weekdays : 'Жекшемби_Дүйшөмбү_Шейшемби_Шаршемби_Бейшемби_Жума_Ишемби'.split('_'), + weekdaysShort : 'Жек_Дүй_Шей_Шар_Бей_Жум_Ише'.split('_'), + weekdaysMin : 'Жк_Дй_Шй_Шр_Бй_Жм_Иш'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Бүгүн саат] LT', + nextDay : '[Эртең саат] LT', + nextWeek : 'dddd [саат] LT', + lastDay : '[Кече саат] LT', + lastWeek : '[Өткен аптанын] dddd [күнү] [саат] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ичинде', + past : '%s мурун', + s : 'бирнече секунд', + m : 'бир мүнөт', + mm : '%d мүнөт', + h : 'бир саат', + hh : '%d саат', + d : 'бир күн', + dd : '%d күн', + M : 'бир ай', + MM : '%d ай', + y : 'бир жыл', + yy : '%d жыл' + }, + ordinalParse: /\d{1,2}-(чи|чы|чү|чу)/, + ordinal : function (number) { + var a = number % 10, + b = number >= 100 ? 100 : null; + return number + (ky__suffixes[number] || ky__suffixes[a] || ky__suffixes[b]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + function lb__processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eng Minutt', 'enger Minutt'], + 'h': ['eng Stonn', 'enger Stonn'], + 'd': ['een Dag', 'engem Dag'], + 'M': ['ee Mount', 'engem Mount'], + 'y': ['ee Joer', 'engem Joer'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; + } + function processFutureTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'a ' + string; + } + return 'an ' + string; + } + function processPastTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'viru ' + string; + } + return 'virun ' + string; + } + /** + * Returns true if the word before the given number loses the '-n' ending. + * e.g. 'an 10 Deeg' but 'a 5 Deeg' + * + * @param number {integer} + * @returns {boolean} + */ + function eifelerRegelAppliesToNumber(number) { + number = parseInt(number, 10); + if (isNaN(number)) { + return false; + } + if (number < 0) { + // Negative Number --> always true + return true; + } else if (number < 10) { + // Only 1 digit + if (4 <= number && number <= 7) { + return true; + } + return false; + } else if (number < 100) { + // 2 digits + var lastDigit = number % 10, firstDigit = number / 10; + if (lastDigit === 0) { + return eifelerRegelAppliesToNumber(firstDigit); + } + return eifelerRegelAppliesToNumber(lastDigit); + } else if (number < 10000) { + // 3 or 4 digits --> recursively check first digit + while (number >= 10) { + number = number / 10; + } + return eifelerRegelAppliesToNumber(number); + } else { + // Anything larger than 4 digits: recursively check first n-3 digits + number = number / 1000; + return eifelerRegelAppliesToNumber(number); + } + } + + var lb = moment__default.defineLocale('lb', { + months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + monthsParseExact : true, + weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'), + weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'), + weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm [Auer]', + LTS: 'H:mm:ss [Auer]', + L: 'DD.MM.YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm [Auer]', + LLLL: 'dddd, D. MMMM YYYY H:mm [Auer]' + }, + calendar: { + sameDay: '[Haut um] LT', + sameElse: 'L', + nextDay: '[Muer um] LT', + nextWeek: 'dddd [um] LT', + lastDay: '[Gëschter um] LT', + lastWeek: function () { + // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule + switch (this.day()) { + case 2: + case 4: + return '[Leschten] dddd [um] LT'; + default: + return '[Leschte] dddd [um] LT'; + } + } + }, + relativeTime : { + future : processFutureTime, + past : processPastTime, + s : 'e puer Sekonnen', + m : lb__processRelativeTime, + mm : '%d Minutten', + h : lb__processRelativeTime, + hh : '%d Stonnen', + d : lb__processRelativeTime, + dd : '%d Deeg', + M : lb__processRelativeTime, + MM : '%d Méint', + y : lb__processRelativeTime, + yy : '%d Joer' + }, + ordinalParse: /\d{1,2}\./, + ordinal: '%d.', + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var lo = moment__default.defineLocale('lo', { + months : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'), + monthsShort : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'), + weekdays : 'ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'), + weekdaysShort : 'ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'), + weekdaysMin : 'ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'ວັນdddd D MMMM YYYY HH:mm' + }, + meridiemParse: /ຕອນເຊົ້າ|ຕອນແລງ/, + isPM: function (input) { + return input === 'ຕອນແລງ'; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ຕອນເຊົ້າ'; + } else { + return 'ຕອນແລງ'; + } + }, + calendar : { + sameDay : '[ມື້ນີ້ເວລາ] LT', + nextDay : '[ມື້ອື່ນເວລາ] LT', + nextWeek : '[ວັນ]dddd[ໜ້າເວລາ] LT', + lastDay : '[ມື້ວານນີ້ເວລາ] LT', + lastWeek : '[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'ອີກ %s', + past : '%sຜ່ານມາ', + s : 'ບໍ່ເທົ່າໃດວິນາທີ', + m : '1 ນາທີ', + mm : '%d ນາທີ', + h : '1 ຊົ່ວໂມງ', + hh : '%d ຊົ່ວໂມງ', + d : '1 ມື້', + dd : '%d ມື້', + M : '1 ເດືອນ', + MM : '%d ເດືອນ', + y : '1 ປີ', + yy : '%d ປີ' + }, + ordinalParse: /(ທີ່)\d{1,2}/, + ordinal : function (number) { + return 'ທີ່' + number; + } + }); + + + var lt__units = { + 'm' : 'minutė_minutės_minutę', + 'mm': 'minutės_minučių_minutes', + 'h' : 'valanda_valandos_valandą', + 'hh': 'valandos_valandų_valandas', + 'd' : 'diena_dienos_dieną', + 'dd': 'dienos_dienų_dienas', + 'M' : 'mėnuo_mėnesio_mėnesį', + 'MM': 'mėnesiai_mėnesių_mėnesius', + 'y' : 'metai_metų_metus', + 'yy': 'metai_metų_metus' + }; + function translateSeconds(number, withoutSuffix, key, isFuture) { + if (withoutSuffix) { + return 'kelios sekundės'; + } else { + return isFuture ? 'kelių sekundžių' : 'kelias sekundes'; + } + } + function translateSingular(number, withoutSuffix, key, isFuture) { + return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]); + } + function special(number) { + return number % 10 === 0 || (number > 10 && number < 20); + } + function forms(key) { + return lt__units[key].split('_'); + } + function lt__translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + if (number === 1) { + return result + translateSingular(number, withoutSuffix, key[0], isFuture); + } else if (withoutSuffix) { + return result + (special(number) ? forms(key)[1] : forms(key)[0]); + } else { + if (isFuture) { + return result + forms(key)[1]; + } else { + return result + (special(number) ? forms(key)[1] : forms(key)[2]); + } + } + } + var lt = moment__default.defineLocale('lt', { + months : { + format: 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'), + standalone: 'sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis'.split('_'), + isFormat: /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?|MMMM?(\[[^\[\]]*\]|\s+)+D[oD]?/ + }, + monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'), + weekdays : { + format: 'sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį'.split('_'), + standalone: 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_'), + isFormat: /dddd HH:mm/ + }, + weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'), + weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'YYYY [m.] MMMM D [d.]', + LLL : 'YYYY [m.] MMMM D [d.], HH:mm [val.]', + LLLL : 'YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]', + l : 'YYYY-MM-DD', + ll : 'YYYY [m.] MMMM D [d.]', + lll : 'YYYY [m.] MMMM D [d.], HH:mm [val.]', + llll : 'YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]' + }, + calendar : { + sameDay : '[Šiandien] LT', + nextDay : '[Rytoj] LT', + nextWeek : 'dddd LT', + lastDay : '[Vakar] LT', + lastWeek : '[Praėjusį] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : 'po %s', + past : 'prieš %s', + s : translateSeconds, + m : translateSingular, + mm : lt__translate, + h : translateSingular, + hh : lt__translate, + d : translateSingular, + dd : lt__translate, + M : translateSingular, + MM : lt__translate, + y : translateSingular, + yy : lt__translate + }, + ordinalParse: /\d{1,2}-oji/, + ordinal : function (number) { + return number + '-oji'; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var lv__units = { + 'm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'mm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'h': 'stundas_stundām_stunda_stundas'.split('_'), + 'hh': 'stundas_stundām_stunda_stundas'.split('_'), + 'd': 'dienas_dienām_diena_dienas'.split('_'), + 'dd': 'dienas_dienām_diena_dienas'.split('_'), + 'M': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'MM': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'y': 'gada_gadiem_gads_gadi'.split('_'), + 'yy': 'gada_gadiem_gads_gadi'.split('_') + }; + /** + * @param withoutSuffix boolean true = a length of time; false = before/after a period of time. + */ + function lv__format(forms, number, withoutSuffix) { + if (withoutSuffix) { + // E.g. "21 minūte", "3 minūtes". + return number % 10 === 1 && number % 100 !== 11 ? forms[2] : forms[3]; + } else { + // E.g. "21 minūtes" as in "pēc 21 minūtes". + // E.g. "3 minūtēm" as in "pēc 3 minūtēm". + return number % 10 === 1 && number % 100 !== 11 ? forms[0] : forms[1]; + } + } + function lv__relativeTimeWithPlural(number, withoutSuffix, key) { + return number + ' ' + lv__format(lv__units[key], number, withoutSuffix); + } + function relativeTimeWithSingular(number, withoutSuffix, key) { + return lv__format(lv__units[key], number, withoutSuffix); + } + function relativeSeconds(number, withoutSuffix) { + return withoutSuffix ? 'dažas sekundes' : 'dažām sekundēm'; + } + + var lv = moment__default.defineLocale('lv', { + months : 'janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec'.split('_'), + weekdays : 'svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena'.split('_'), + weekdaysShort : 'Sv_P_O_T_C_Pk_S'.split('_'), + weekdaysMin : 'Sv_P_O_T_C_Pk_S'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY.', + LL : 'YYYY. [gada] D. MMMM', + LLL : 'YYYY. [gada] D. MMMM, HH:mm', + LLLL : 'YYYY. [gada] D. MMMM, dddd, HH:mm' + }, + calendar : { + sameDay : '[Šodien pulksten] LT', + nextDay : '[Rīt pulksten] LT', + nextWeek : 'dddd [pulksten] LT', + lastDay : '[Vakar pulksten] LT', + lastWeek : '[Pagājušā] dddd [pulksten] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'pēc %s', + past : 'pirms %s', + s : relativeSeconds, + m : relativeTimeWithSingular, + mm : lv__relativeTimeWithPlural, + h : relativeTimeWithSingular, + hh : lv__relativeTimeWithPlural, + d : relativeTimeWithSingular, + dd : lv__relativeTimeWithPlural, + M : relativeTimeWithSingular, + MM : lv__relativeTimeWithPlural, + y : relativeTimeWithSingular, + yy : lv__relativeTimeWithPlural + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var me__translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jednog minuta'], + mm: ['minut', 'minuta', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mjesec', 'mjeseca', 'mjeseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = me__translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + me__translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var me = moment__default.defineLocale('me', { + months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'), + monthsParseExact : true, + weekdays: 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort: 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm', + LTS : 'H:mm:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm', + LLLL: 'dddd, D. MMMM YYYY H:mm' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sjutra u] LT', + + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedjelje] [u] LT', + '[prošlog] [ponedjeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srijede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'nekoliko sekundi', + m : me__translator.translate, + mm : me__translator.translate, + h : me__translator.translate, + hh : me__translator.translate, + d : 'dan', + dd : me__translator.translate, + M : 'mjesec', + MM : me__translator.translate, + y : 'godinu', + yy : me__translator.translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var mk = moment__default.defineLocale('mk', { + months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'), + weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'), + weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'D.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd, D MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[Денес во] LT', + nextDay : '[Утре во] LT', + nextWeek : '[Во] dddd [во] LT', + lastDay : '[Вчера во] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + case 6: + return '[Изминатата] dddd [во] LT'; + case 1: + case 2: + case 4: + case 5: + return '[Изминатиот] dddd [во] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'после %s', + past : 'пред %s', + s : 'неколку секунди', + m : 'минута', + mm : '%d минути', + h : 'час', + hh : '%d часа', + d : 'ден', + dd : '%d дена', + M : 'месец', + MM : '%d месеци', + y : 'година', + yy : '%d години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + ordinal : function (number) { + var lastDigit = number % 10, + last2Digits = number % 100; + if (number === 0) { + return number + '-ев'; + } else if (last2Digits === 0) { + return number + '-ен'; + } else if (last2Digits > 10 && last2Digits < 20) { + return number + '-ти'; + } else if (lastDigit === 1) { + return number + '-ви'; + } else if (lastDigit === 2) { + return number + '-ри'; + } else if (lastDigit === 7 || lastDigit === 8) { + return number + '-ми'; + } else { + return number + '-ти'; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var ml = moment__default.defineLocale('ml', { + months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'), + monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'), + monthsParseExact : true, + weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'), + weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'), + weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'), + longDateFormat : { + LT : 'A h:mm -നു', + LTS : 'A h:mm:ss -നു', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm -നു', + LLLL : 'dddd, D MMMM YYYY, A h:mm -നു' + }, + calendar : { + sameDay : '[ഇന്ന്] LT', + nextDay : '[നാളെ] LT', + nextWeek : 'dddd, LT', + lastDay : '[ഇന്നലെ] LT', + lastWeek : '[കഴിഞ്ഞ] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s കഴിഞ്ഞ്', + past : '%s മുൻപ്', + s : 'അൽപ നിമിഷങ്ങൾ', + m : 'ഒരു മിനിറ്റ്', + mm : '%d മിനിറ്റ്', + h : 'ഒരു മണിക്കൂർ', + hh : '%d മണിക്കൂർ', + d : 'ഒരു ദിവസം', + dd : '%d ദിവസം', + M : 'ഒരു മാസം', + MM : '%d മാസം', + y : 'ഒരു വർഷം', + yy : '%d വർഷം' + }, + meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if ((meridiem === 'രാത്രി' && hour >= 4) || + meridiem === 'ഉച്ച കഴിഞ്ഞ്' || + meridiem === 'വൈകുന്നേരം') { + return hour + 12; + } else { + return hour; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'രാത്രി'; + } else if (hour < 12) { + return 'രാവിലെ'; + } else if (hour < 17) { + return 'ഉച്ച കഴിഞ്ഞ്'; + } else if (hour < 20) { + return 'വൈകുന്നേരം'; + } else { + return 'രാത്രി'; + } + } + }); + + + var mr__symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + mr__numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + function relativeTimeMr(number, withoutSuffix, string, isFuture) + { + var output = ''; + if (withoutSuffix) { + switch (string) { + case 's': output = 'काही सेकंद'; break; + case 'm': output = 'एक मिनिट'; break; + case 'mm': output = '%d मिनिटे'; break; + case 'h': output = 'एक तास'; break; + case 'hh': output = '%d तास'; break; + case 'd': output = 'एक दिवस'; break; + case 'dd': output = '%d दिवस'; break; + case 'M': output = 'एक महिना'; break; + case 'MM': output = '%d महिने'; break; + case 'y': output = 'एक वर्ष'; break; + case 'yy': output = '%d वर्षे'; break; + } + } + else { + switch (string) { + case 's': output = 'काही सेकंदां'; break; + case 'm': output = 'एका मिनिटा'; break; + case 'mm': output = '%d मिनिटां'; break; + case 'h': output = 'एका तासा'; break; + case 'hh': output = '%d तासां'; break; + case 'd': output = 'एका दिवसा'; break; + case 'dd': output = '%d दिवसां'; break; + case 'M': output = 'एका महिन्या'; break; + case 'MM': output = '%d महिन्यां'; break; + case 'y': output = 'एका वर्षा'; break; + case 'yy': output = '%d वर्षां'; break; + } + } + return output.replace(/%d/i, number); + } + + var mr = moment__default.defineLocale('mr', { + months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'), + monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'), + monthsParseExact : true, + weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm वाजता', + LTS : 'A h:mm:ss वाजता', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm वाजता', + LLLL : 'dddd, D MMMM YYYY, A h:mm वाजता' + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[उद्या] LT', + nextWeek : 'dddd, LT', + lastDay : '[काल] LT', + lastWeek: '[मागील] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future: '%sमध्ये', + past: '%sपूर्वी', + s: relativeTimeMr, + m: relativeTimeMr, + mm: relativeTimeMr, + h: relativeTimeMr, + hh: relativeTimeMr, + d: relativeTimeMr, + dd: relativeTimeMr, + M: relativeTimeMr, + MM: relativeTimeMr, + y: relativeTimeMr, + yy: relativeTimeMr + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return mr__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return mr__symbolMap[match]; + }); + }, + meridiemParse: /रात्री|सकाळी|दुपारी|सायंकाळी/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात्री') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सकाळी') { + return hour; + } else if (meridiem === 'दुपारी') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'सायंकाळी') { + return hour + 12; + } + }, + meridiem: function (hour, minute, isLower) { + if (hour < 4) { + return 'रात्री'; + } else if (hour < 10) { + return 'सकाळी'; + } else if (hour < 17) { + return 'दुपारी'; + } else if (hour < 20) { + return 'सायंकाळी'; + } else { + return 'रात्री'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var ms_my = moment__default.defineLocale('ms-my', { + months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'), + monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'), + weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'), + weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'), + weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /pagi|tengahari|petang|malam/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'tengahari') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'petang' || meridiem === 'malam') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'tengahari'; + } else if (hours < 19) { + return 'petang'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Esok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kelmarin pukul] LT', + lastWeek : 'dddd [lepas pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'dalam %s', + past : '%s yang lepas', + s : 'beberapa saat', + m : 'seminit', + mm : '%d minit', + h : 'sejam', + hh : '%d jam', + d : 'sehari', + dd : '%d hari', + M : 'sebulan', + MM : '%d bulan', + y : 'setahun', + yy : '%d tahun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var locale_ms = moment__default.defineLocale('ms', { + months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'), + monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'), + weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'), + weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'), + weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /pagi|tengahari|petang|malam/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'tengahari') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'petang' || meridiem === 'malam') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'tengahari'; + } else if (hours < 19) { + return 'petang'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Esok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kelmarin pukul] LT', + lastWeek : 'dddd [lepas pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'dalam %s', + past : '%s yang lepas', + s : 'beberapa saat', + m : 'seminit', + mm : '%d minit', + h : 'sejam', + hh : '%d jam', + d : 'sehari', + dd : '%d hari', + M : 'sebulan', + MM : '%d bulan', + y : 'setahun', + yy : '%d tahun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var my__symbolMap = { + '1': '၁', + '2': '၂', + '3': '၃', + '4': '၄', + '5': '၅', + '6': '၆', + '7': '၇', + '8': '၈', + '9': '၉', + '0': '၀' + }, my__numberMap = { + '၁': '1', + '၂': '2', + '၃': '3', + '၄': '4', + '၅': '5', + '၆': '6', + '၇': '7', + '၈': '8', + '၉': '9', + '၀': '0' + }; + + var my = moment__default.defineLocale('my', { + months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'), + monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'), + weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'), + weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + + longDateFormat: { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[ယနေ.] LT [မှာ]', + nextDay: '[မနက်ဖြန်] LT [မှာ]', + nextWeek: 'dddd LT [မှာ]', + lastDay: '[မနေ.က] LT [မှာ]', + lastWeek: '[ပြီးခဲ့သော] dddd LT [မှာ]', + sameElse: 'L' + }, + relativeTime: { + future: 'လာမည့် %s မှာ', + past: 'လွန်ခဲ့သော %s က', + s: 'စက္ကန်.အနည်းငယ်', + m: 'တစ်မိနစ်', + mm: '%d မိနစ်', + h: 'တစ်နာရီ', + hh: '%d နာရီ', + d: 'တစ်ရက်', + dd: '%d ရက်', + M: 'တစ်လ', + MM: '%d လ', + y: 'တစ်နှစ်', + yy: '%d နှစ်' + }, + preparse: function (string) { + return string.replace(/[၁၂၃၄၅၆၇၈၉၀]/g, function (match) { + return my__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return my__symbolMap[match]; + }); + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var nb = moment__default.defineLocale('nb', { + months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.'.split('_'), + monthsParseExact : true, + weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'), + weekdaysShort : 'sø._ma._ti._on._to._fr._lø.'.split('_'), + weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] HH:mm', + LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm' + }, + calendar : { + sameDay: '[i dag kl.] LT', + nextDay: '[i morgen kl.] LT', + nextWeek: 'dddd [kl.] LT', + lastDay: '[i går kl.] LT', + lastWeek: '[forrige] dddd [kl.] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : '%s siden', + s : 'noen sekunder', + m : 'ett minutt', + mm : '%d minutter', + h : 'en time', + hh : '%d timer', + d : 'en dag', + dd : '%d dager', + M : 'en måned', + MM : '%d måneder', + y : 'ett år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var ne__symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + ne__numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var ne = moment__default.defineLocale('ne', { + months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'), + monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'), + monthsParseExact : true, + weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'), + weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'), + weekdaysMin : 'आ._सो._मं._बु._बि._शु._श.'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'Aको h:mm बजे', + LTS : 'Aको h:mm:ss बजे', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, Aको h:mm बजे', + LLLL : 'dddd, D MMMM YYYY, Aको h:mm बजे' + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return ne__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return ne__symbolMap[match]; + }); + }, + meridiemParse: /राति|बिहान|दिउँसो|साँझ/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'राति') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'बिहान') { + return hour; + } else if (meridiem === 'दिउँसो') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'साँझ') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 3) { + return 'राति'; + } else if (hour < 12) { + return 'बिहान'; + } else if (hour < 16) { + return 'दिउँसो'; + } else if (hour < 20) { + return 'साँझ'; + } else { + return 'राति'; + } + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[भोलि] LT', + nextWeek : '[आउँदो] dddd[,] LT', + lastDay : '[हिजो] LT', + lastWeek : '[गएको] dddd[,] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%sमा', + past : '%s अगाडि', + s : 'केही क्षण', + m : 'एक मिनेट', + mm : '%d मिनेट', + h : 'एक घण्टा', + hh : '%d घण्टा', + d : 'एक दिन', + dd : '%d दिन', + M : 'एक महिना', + MM : '%d महिना', + y : 'एक बर्ष', + yy : '%d बर्ष' + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var nl__monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_'), + nl__monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_'); + + var nl = moment__default.defineLocale('nl', { + months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return nl__monthsShortWithoutDots[m.month()]; + } else { + return nl__monthsShortWithDots[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'), + weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'), + weekdaysMin : 'Zo_Ma_Di_Wo_Do_Vr_Za'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[vandaag om] LT', + nextDay: '[morgen om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[gisteren om] LT', + lastWeek: '[afgelopen] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'over %s', + past : '%s geleden', + s : 'een paar seconden', + m : 'één minuut', + mm : '%d minuten', + h : 'één uur', + hh : '%d uur', + d : 'één dag', + dd : '%d dagen', + M : 'één maand', + MM : '%d maanden', + y : 'één jaar', + yy : '%d jaar' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var nn = moment__default.defineLocale('nn', { + months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), + weekdays : 'sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag'.split('_'), + weekdaysShort : 'sun_mån_tys_ons_tor_fre_lau'.split('_'), + weekdaysMin : 'su_må_ty_on_to_fr_lø'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] H:mm', + LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm' + }, + calendar : { + sameDay: '[I dag klokka] LT', + nextDay: '[I morgon klokka] LT', + nextWeek: 'dddd [klokka] LT', + lastDay: '[I går klokka] LT', + lastWeek: '[Føregåande] dddd [klokka] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : '%s sidan', + s : 'nokre sekund', + m : 'eit minutt', + mm : '%d minutt', + h : 'ein time', + hh : '%d timar', + d : 'ein dag', + dd : '%d dagar', + M : 'ein månad', + MM : '%d månader', + y : 'eit år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var pa_in__symbolMap = { + '1': '੧', + '2': '੨', + '3': '੩', + '4': '੪', + '5': '੫', + '6': '੬', + '7': '੭', + '8': '੮', + '9': '੯', + '0': '੦' + }, + pa_in__numberMap = { + '੧': '1', + '੨': '2', + '੩': '3', + '੪': '4', + '੫': '5', + '੬': '6', + '੭': '7', + '੮': '8', + '੯': '9', + '੦': '0' + }; + + var pa_in = moment__default.defineLocale('pa-in', { + // There are months name as per Nanakshahi Calender but they are not used as rigidly in modern Punjabi. + months : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'), + monthsShort : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'), + weekdays : 'ਐਤਵਾਰ_ਸੋਮਵਾਰ_ਮੰਗਲਵਾਰ_ਬੁਧਵਾਰ_ਵੀਰਵਾਰ_ਸ਼ੁੱਕਰਵਾਰ_ਸ਼ਨੀਚਰਵਾਰ'.split('_'), + weekdaysShort : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'), + weekdaysMin : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'), + longDateFormat : { + LT : 'A h:mm ਵਜੇ', + LTS : 'A h:mm:ss ਵਜੇ', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm ਵਜੇ', + LLLL : 'dddd, D MMMM YYYY, A h:mm ਵਜੇ' + }, + calendar : { + sameDay : '[ਅਜ] LT', + nextDay : '[ਕਲ] LT', + nextWeek : 'dddd, LT', + lastDay : '[ਕਲ] LT', + lastWeek : '[ਪਿਛਲੇ] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ਵਿੱਚ', + past : '%s ਪਿਛਲੇ', + s : 'ਕੁਝ ਸਕਿੰਟ', + m : 'ਇਕ ਮਿੰਟ', + mm : '%d ਮਿੰਟ', + h : 'ਇੱਕ ਘੰਟਾ', + hh : '%d ਘੰਟੇ', + d : 'ਇੱਕ ਦਿਨ', + dd : '%d ਦਿਨ', + M : 'ਇੱਕ ਮਹੀਨਾ', + MM : '%d ਮਹੀਨੇ', + y : 'ਇੱਕ ਸਾਲ', + yy : '%d ਸਾਲ' + }, + preparse: function (string) { + return string.replace(/[੧੨੩੪੫੬੭੮੯੦]/g, function (match) { + return pa_in__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return pa_in__symbolMap[match]; + }); + }, + // Punjabi notation for meridiems are quite fuzzy in practice. While there exists + // a rigid notion of a 'Pahar' it is not used as rigidly in modern Punjabi. + meridiemParse: /ਰਾਤ|ਸਵੇਰ|ਦੁਪਹਿਰ|ਸ਼ਾਮ/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'ਰਾਤ') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'ਸਵੇਰ') { + return hour; + } else if (meridiem === 'ਦੁਪਹਿਰ') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'ਸ਼ਾਮ') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ਰਾਤ'; + } else if (hour < 10) { + return 'ਸਵੇਰ'; + } else if (hour < 17) { + return 'ਦੁਪਹਿਰ'; + } else if (hour < 20) { + return 'ਸ਼ਾਮ'; + } else { + return 'ਰਾਤ'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split('_'), + monthsSubjective = 'stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia'.split('_'); + function pl__plural(n) { + return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1); + } + function pl__translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'minuta' : 'minutę'; + case 'mm': + return result + (pl__plural(number) ? 'minuty' : 'minut'); + case 'h': + return withoutSuffix ? 'godzina' : 'godzinę'; + case 'hh': + return result + (pl__plural(number) ? 'godziny' : 'godzin'); + case 'MM': + return result + (pl__plural(number) ? 'miesiące' : 'miesięcy'); + case 'yy': + return result + (pl__plural(number) ? 'lata' : 'lat'); + } + } + + var pl = moment__default.defineLocale('pl', { + months : function (momentToFormat, format) { + if (format === '') { + // Hack: if format empty we know this is used to generate + // RegExp by moment. Give then back both valid forms of months + // in RegExp ready format. + return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')'; + } else if (/D MMMM/.test(format)) { + return monthsSubjective[momentToFormat.month()]; + } else { + return monthsNominative[momentToFormat.month()]; + } + }, + monthsShort : 'sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru'.split('_'), + weekdays : 'niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota'.split('_'), + weekdaysShort : 'nie_pon_wt_śr_czw_pt_sb'.split('_'), + weekdaysMin : 'Nd_Pn_Wt_Śr_Cz_Pt_So'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Dziś o] LT', + nextDay: '[Jutro o] LT', + nextWeek: '[W] dddd [o] LT', + lastDay: '[Wczoraj o] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[W zeszłą niedzielę o] LT'; + case 3: + return '[W zeszłą środę o] LT'; + case 6: + return '[W zeszłą sobotę o] LT'; + default: + return '[W zeszły] dddd [o] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'za %s', + past : '%s temu', + s : 'kilka sekund', + m : pl__translate, + mm : pl__translate, + h : pl__translate, + hh : pl__translate, + d : '1 dzień', + dd : '%d dni', + M : 'miesiąc', + MM : pl__translate, + y : 'rok', + yy : pl__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var pt_br = moment__default.defineLocale('pt-br', { + months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'), + monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'), + weekdays : 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split('_'), + weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'), + weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY [às] HH:mm', + LLLL : 'dddd, D [de] MMMM [de] YYYY [às] HH:mm' + }, + calendar : { + sameDay: '[Hoje às] LT', + nextDay: '[Amanhã às] LT', + nextWeek: 'dddd [às] LT', + lastDay: '[Ontem às] LT', + lastWeek: function () { + return (this.day() === 0 || this.day() === 6) ? + '[Último] dddd [às] LT' : // Saturday + Sunday + '[Última] dddd [às] LT'; // Monday - Friday + }, + sameElse: 'L' + }, + relativeTime : { + future : 'em %s', + past : '%s atrás', + s : 'poucos segundos', + m : 'um minuto', + mm : '%d minutos', + h : 'uma hora', + hh : '%d horas', + d : 'um dia', + dd : '%d dias', + M : 'um mês', + MM : '%d meses', + y : 'um ano', + yy : '%d anos' + }, + ordinalParse: /\d{1,2}º/, + ordinal : '%dº' + }); + + + var pt = moment__default.defineLocale('pt', { + months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'), + monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'), + weekdays : 'Domingo_Segunda-Feira_Terça-Feira_Quarta-Feira_Quinta-Feira_Sexta-Feira_Sábado'.split('_'), + weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'), + weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY HH:mm', + LLLL : 'dddd, D [de] MMMM [de] YYYY HH:mm' + }, + calendar : { + sameDay: '[Hoje às] LT', + nextDay: '[Amanhã às] LT', + nextWeek: 'dddd [às] LT', + lastDay: '[Ontem às] LT', + lastWeek: function () { + return (this.day() === 0 || this.day() === 6) ? + '[Último] dddd [às] LT' : // Saturday + Sunday + '[Última] dddd [às] LT'; // Monday - Friday + }, + sameElse: 'L' + }, + relativeTime : { + future : 'em %s', + past : 'há %s', + s : 'segundos', + m : 'um minuto', + mm : '%d minutos', + h : 'uma hora', + hh : '%d horas', + d : 'um dia', + dd : '%d dias', + M : 'um mês', + MM : '%d meses', + y : 'um ano', + yy : '%d anos' + }, + ordinalParse: /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + function ro__relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': 'minute', + 'hh': 'ore', + 'dd': 'zile', + 'MM': 'luni', + 'yy': 'ani' + }, + separator = ' '; + if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) { + separator = ' de '; + } + return number + separator + format[key]; + } + + var ro = moment__default.defineLocale('ro', { + months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'), + monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays : 'duminică_luni_marți_miercuri_joi_vineri_sâmbătă'.split('_'), + weekdaysShort : 'Dum_Lun_Mar_Mie_Joi_Vin_Sâm'.split('_'), + weekdaysMin : 'Du_Lu_Ma_Mi_Jo_Vi_Sâ'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd, D MMMM YYYY H:mm' + }, + calendar : { + sameDay: '[azi la] LT', + nextDay: '[mâine la] LT', + nextWeek: 'dddd [la] LT', + lastDay: '[ieri la] LT', + lastWeek: '[fosta] dddd [la] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'peste %s', + past : '%s în urmă', + s : 'câteva secunde', + m : 'un minut', + mm : ro__relativeTimeWithPlural, + h : 'o oră', + hh : ro__relativeTimeWithPlural, + d : 'o zi', + dd : ro__relativeTimeWithPlural, + M : 'o lună', + MM : ro__relativeTimeWithPlural, + y : 'un an', + yy : ro__relativeTimeWithPlural + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + function ru__plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); + } + function ru__relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут', + 'hh': 'час_часа_часов', + 'dd': 'день_дня_дней', + 'MM': 'месяц_месяца_месяцев', + 'yy': 'год_года_лет' + }; + if (key === 'm') { + return withoutSuffix ? 'минута' : 'минуту'; + } + else { + return number + ' ' + ru__plural(format[key], +number); + } + } + var monthsParse = [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[йя]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i]; + + // http://new.gramota.ru/spravka/rules/139-prop : § 103 + // Сокращения месяцев: http://new.gramota.ru/spravka/buro/search-answer?s=242637 + // CLDR data: http://www.unicode.org/cldr/charts/28/summary/ru.html#1753 + var ru = moment__default.defineLocale('ru', { + months : { + format: 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_'), + standalone: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_') + }, + monthsShort : { + // по CLDR именно "июл." и "июн.", но какой смысл менять букву на точку ? + format: 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split('_'), + standalone: 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split('_') + }, + weekdays : { + standalone: 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'), + format: 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_'), + isFormat: /\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/ + }, + weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + monthsParse : monthsParse, + longMonthsParse : monthsParse, + shortMonthsParse : monthsParse, + + // полные названия с падежами, по три буквы, для некоторых, по 4 буквы, сокращения с точкой и без точки + monthsRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i, + + // копия предыдущего + monthsShortRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i, + + // полные названия с падежами + monthsStrictRegex: /^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i, + + // Выражение, которое соотвествует только сокращённым формам + monthsShortStrictRegex: /^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY г.', + LLL : 'D MMMM YYYY г., HH:mm', + LLLL : 'dddd, D MMMM YYYY г., HH:mm' + }, + calendar : { + sameDay: '[Сегодня в] LT', + nextDay: '[Завтра в] LT', + lastDay: '[Вчера в] LT', + nextWeek: function (now) { + if (now.week() !== this.week()) { + switch (this.day()) { + case 0: + return '[В следующее] dddd [в] LT'; + case 1: + case 2: + case 4: + return '[В следующий] dddd [в] LT'; + case 3: + case 5: + case 6: + return '[В следующую] dddd [в] LT'; + } + } else { + if (this.day() === 2) { + return '[Во] dddd [в] LT'; + } else { + return '[В] dddd [в] LT'; + } + } + }, + lastWeek: function (now) { + if (now.week() !== this.week()) { + switch (this.day()) { + case 0: + return '[В прошлое] dddd [в] LT'; + case 1: + case 2: + case 4: + return '[В прошлый] dddd [в] LT'; + case 3: + case 5: + case 6: + return '[В прошлую] dddd [в] LT'; + } + } else { + if (this.day() === 2) { + return '[Во] dddd [в] LT'; + } else { + return '[В] dddd [в] LT'; + } + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'через %s', + past : '%s назад', + s : 'несколько секунд', + m : ru__relativeTimeWithPlural, + mm : ru__relativeTimeWithPlural, + h : 'час', + hh : ru__relativeTimeWithPlural, + d : 'день', + dd : ru__relativeTimeWithPlural, + M : 'месяц', + MM : ru__relativeTimeWithPlural, + y : 'год', + yy : ru__relativeTimeWithPlural + }, + meridiemParse: /ночи|утра|дня|вечера/i, + isPM : function (input) { + return /^(дня|вечера)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночи'; + } else if (hour < 12) { + return 'утра'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечера'; + } + }, + ordinalParse: /\d{1,2}-(й|го|я)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + return number + '-й'; + case 'D': + return number + '-го'; + case 'w': + case 'W': + return number + '-я'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + + var se = moment__default.defineLocale('se', { + months : 'ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu'.split('_'), + monthsShort : 'ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov'.split('_'), + weekdays : 'sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat'.split('_'), + weekdaysShort : 'sotn_vuos_maŋ_gask_duor_bear_láv'.split('_'), + weekdaysMin : 's_v_m_g_d_b_L'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'MMMM D. [b.] YYYY', + LLL : 'MMMM D. [b.] YYYY [ti.] HH:mm', + LLLL : 'dddd, MMMM D. [b.] YYYY [ti.] HH:mm' + }, + calendar : { + sameDay: '[otne ti] LT', + nextDay: '[ihttin ti] LT', + nextWeek: 'dddd [ti] LT', + lastDay: '[ikte ti] LT', + lastWeek: '[ovddit] dddd [ti] LT', + sameElse: 'L' + }, + relativeTime : { + future : '%s geažes', + past : 'maŋit %s', + s : 'moadde sekunddat', + m : 'okta minuhta', + mm : '%d minuhtat', + h : 'okta diimmu', + hh : '%d diimmut', + d : 'okta beaivi', + dd : '%d beaivvit', + M : 'okta mánnu', + MM : '%d mánut', + y : 'okta jahki', + yy : '%d jagit' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + /*jshint -W100*/ + var si = moment__default.defineLocale('si', { + months : 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split('_'), + monthsShort : 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split('_'), + weekdays : 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split('_'), + weekdaysShort : 'ඉරි_සඳු_අඟ_බදා_බ්රහ_සිකු_සෙන'.split('_'), + weekdaysMin : 'ඉ_ස_අ_බ_බ්ර_සි_සෙ'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'a h:mm', + LTS : 'a h:mm:ss', + L : 'YYYY/MM/DD', + LL : 'YYYY MMMM D', + LLL : 'YYYY MMMM D, a h:mm', + LLLL : 'YYYY MMMM D [වැනි] dddd, a h:mm:ss' + }, + calendar : { + sameDay : '[අද] LT[ට]', + nextDay : '[හෙට] LT[ට]', + nextWeek : 'dddd LT[ට]', + lastDay : '[ඊයේ] LT[ට]', + lastWeek : '[පසුගිය] dddd LT[ට]', + sameElse : 'L' + }, + relativeTime : { + future : '%sකින්', + past : '%sකට පෙර', + s : 'තත්පර කිහිපය', + m : 'මිනිත්තුව', + mm : 'මිනිත්තු %d', + h : 'පැය', + hh : 'පැය %d', + d : 'දිනය', + dd : 'දින %d', + M : 'මාසය', + MM : 'මාස %d', + y : 'වසර', + yy : 'වසර %d' + }, + ordinalParse: /\d{1,2} වැනි/, + ordinal : function (number) { + return number + ' වැනි'; + }, + meridiemParse : /පෙර වරු|පස් වරු|පෙ.ව|ප.ව./, + isPM : function (input) { + return input === 'ප.ව.' || input === 'පස් වරු'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'ප.ව.' : 'පස් වරු'; + } else { + return isLower ? 'පෙ.ව.' : 'පෙර වරු'; + } + } + }); + + + var sk__months = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_'), + sk__monthsShort = 'jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec'.split('_'); + function sk__plural(n) { + return (n > 1) && (n < 5); + } + function sk__translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': // a few seconds / in a few seconds / a few seconds ago + return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami'; + case 'm': // a minute / in a minute / a minute ago + return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou'); + case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago + if (withoutSuffix || isFuture) { + return result + (sk__plural(number) ? 'minúty' : 'minút'); + } else { + return result + 'minútami'; + } + break; + case 'h': // an hour / in an hour / an hour ago + return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou'); + case 'hh': // 9 hours / in 9 hours / 9 hours ago + if (withoutSuffix || isFuture) { + return result + (sk__plural(number) ? 'hodiny' : 'hodín'); + } else { + return result + 'hodinami'; + } + break; + case 'd': // a day / in a day / a day ago + return (withoutSuffix || isFuture) ? 'deň' : 'dňom'; + case 'dd': // 9 days / in 9 days / 9 days ago + if (withoutSuffix || isFuture) { + return result + (sk__plural(number) ? 'dni' : 'dní'); + } else { + return result + 'dňami'; + } + break; + case 'M': // a month / in a month / a month ago + return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom'; + case 'MM': // 9 months / in 9 months / 9 months ago + if (withoutSuffix || isFuture) { + return result + (sk__plural(number) ? 'mesiace' : 'mesiacov'); + } else { + return result + 'mesiacmi'; + } + break; + case 'y': // a year / in a year / a year ago + return (withoutSuffix || isFuture) ? 'rok' : 'rokom'; + case 'yy': // 9 years / in 9 years / 9 years ago + if (withoutSuffix || isFuture) { + return result + (sk__plural(number) ? 'roky' : 'rokov'); + } else { + return result + 'rokmi'; + } + break; + } + } + + var sk = moment__default.defineLocale('sk', { + months : sk__months, + monthsShort : sk__monthsShort, + weekdays : 'nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota'.split('_'), + weekdaysShort : 'ne_po_ut_st_št_pi_so'.split('_'), + weekdaysMin : 'ne_po_ut_st_št_pi_so'.split('_'), + longDateFormat : { + LT: 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd D. MMMM YYYY H:mm' + }, + calendar : { + sameDay: '[dnes o] LT', + nextDay: '[zajtra o] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[v nedeľu o] LT'; + case 1: + case 2: + return '[v] dddd [o] LT'; + case 3: + return '[v stredu o] LT'; + case 4: + return '[vo štvrtok o] LT'; + case 5: + return '[v piatok o] LT'; + case 6: + return '[v sobotu o] LT'; + } + }, + lastDay: '[včera o] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[minulú nedeľu o] LT'; + case 1: + case 2: + return '[minulý] dddd [o] LT'; + case 3: + return '[minulú stredu o] LT'; + case 4: + case 5: + return '[minulý] dddd [o] LT'; + case 6: + return '[minulú sobotu o] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'za %s', + past : 'pred %s', + s : sk__translate, + m : sk__translate, + mm : sk__translate, + h : sk__translate, + hh : sk__translate, + d : sk__translate, + dd : sk__translate, + M : sk__translate, + MM : sk__translate, + y : sk__translate, + yy : sk__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + function sl__processRelativeTime(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nekaj sekund' : 'nekaj sekundami'; + case 'm': + return withoutSuffix ? 'ena minuta' : 'eno minuto'; + case 'mm': + if (number === 1) { + result += withoutSuffix ? 'minuta' : 'minuto'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'minuti' : 'minutama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'minute' : 'minutami'; + } else { + result += withoutSuffix || isFuture ? 'minut' : 'minutami'; + } + return result; + case 'h': + return withoutSuffix ? 'ena ura' : 'eno uro'; + case 'hh': + if (number === 1) { + result += withoutSuffix ? 'ura' : 'uro'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'uri' : 'urama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'ure' : 'urami'; + } else { + result += withoutSuffix || isFuture ? 'ur' : 'urami'; + } + return result; + case 'd': + return withoutSuffix || isFuture ? 'en dan' : 'enim dnem'; + case 'dd': + if (number === 1) { + result += withoutSuffix || isFuture ? 'dan' : 'dnem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'dni' : 'dnevoma'; + } else { + result += withoutSuffix || isFuture ? 'dni' : 'dnevi'; + } + return result; + case 'M': + return withoutSuffix || isFuture ? 'en mesec' : 'enim mesecem'; + case 'MM': + if (number === 1) { + result += withoutSuffix || isFuture ? 'mesec' : 'mesecem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'meseca' : 'mesecema'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'mesece' : 'meseci'; + } else { + result += withoutSuffix || isFuture ? 'mesecev' : 'meseci'; + } + return result; + case 'y': + return withoutSuffix || isFuture ? 'eno leto' : 'enim letom'; + case 'yy': + if (number === 1) { + result += withoutSuffix || isFuture ? 'leto' : 'letom'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'leti' : 'letoma'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'leta' : 'leti'; + } else { + result += withoutSuffix || isFuture ? 'let' : 'leti'; + } + return result; + } + } + + var sl = moment__default.defineLocale('sl', { + months : 'januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december'.split('_'), + monthsShort : 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays : 'nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota'.split('_'), + weekdaysShort : 'ned._pon._tor._sre._čet._pet._sob.'.split('_'), + weekdaysMin : 'ne_po_to_sr_če_pe_so'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[danes ob] LT', + nextDay : '[jutri ob] LT', + + nextWeek : function () { + switch (this.day()) { + case 0: + return '[v] [nedeljo] [ob] LT'; + case 3: + return '[v] [sredo] [ob] LT'; + case 6: + return '[v] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[v] dddd [ob] LT'; + } + }, + lastDay : '[včeraj ob] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + return '[prejšnjo] [nedeljo] [ob] LT'; + case 3: + return '[prejšnjo] [sredo] [ob] LT'; + case 6: + return '[prejšnjo] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prejšnji] dddd [ob] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'čez %s', + past : 'pred %s', + s : sl__processRelativeTime, + m : sl__processRelativeTime, + mm : sl__processRelativeTime, + h : sl__processRelativeTime, + hh : sl__processRelativeTime, + d : sl__processRelativeTime, + dd : sl__processRelativeTime, + M : sl__processRelativeTime, + MM : sl__processRelativeTime, + y : sl__processRelativeTime, + yy : sl__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var sq = moment__default.defineLocale('sq', { + months : 'Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor'.split('_'), + monthsShort : 'Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj'.split('_'), + weekdays : 'E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë'.split('_'), + weekdaysShort : 'Die_Hën_Mar_Mër_Enj_Pre_Sht'.split('_'), + weekdaysMin : 'D_H_Ma_Më_E_P_Sh'.split('_'), + weekdaysParseExact : true, + meridiemParse: /PD|MD/, + isPM: function (input) { + return input.charAt(0) === 'M'; + }, + meridiem : function (hours, minutes, isLower) { + return hours < 12 ? 'PD' : 'MD'; + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Sot në] LT', + nextDay : '[Nesër në] LT', + nextWeek : 'dddd [në] LT', + lastDay : '[Dje në] LT', + lastWeek : 'dddd [e kaluar në] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'në %s', + past : '%s më parë', + s : 'disa sekonda', + m : 'një minutë', + mm : '%d minuta', + h : 'një orë', + hh : '%d orë', + d : 'një ditë', + dd : '%d ditë', + M : 'një muaj', + MM : '%d muaj', + y : 'një vit', + yy : '%d vite' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var sr_cyrl__translator = { + words: { //Different grammatical cases + m: ['један минут', 'једне минуте'], + mm: ['минут', 'минуте', 'минута'], + h: ['један сат', 'једног сата'], + hh: ['сат', 'сата', 'сати'], + dd: ['дан', 'дана', 'дана'], + MM: ['месец', 'месеца', 'месеци'], + yy: ['година', 'године', 'година'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = sr_cyrl__translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + sr_cyrl__translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var sr_cyrl = moment__default.defineLocale('sr-cyrl', { + months: 'јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар'.split('_'), + monthsShort: 'јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.'.split('_'), + monthsParseExact: true, + weekdays: 'недеља_понедељак_уторак_среда_четвртак_петак_субота'.split('_'), + weekdaysShort: 'нед._пон._уто._сре._чет._пет._суб.'.split('_'), + weekdaysMin: 'не_по_ут_ср_че_пе_су'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm', + LTS : 'H:mm:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm', + LLLL: 'dddd, D. MMMM YYYY H:mm' + }, + calendar: { + sameDay: '[данас у] LT', + nextDay: '[сутра у] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[у] [недељу] [у] LT'; + case 3: + return '[у] [среду] [у] LT'; + case 6: + return '[у] [суботу] [у] LT'; + case 1: + case 2: + case 4: + case 5: + return '[у] dddd [у] LT'; + } + }, + lastDay : '[јуче у] LT', + lastWeek : function () { + var lastWeekDays = [ + '[прошле] [недеље] [у] LT', + '[прошлог] [понедељка] [у] LT', + '[прошлог] [уторка] [у] LT', + '[прошле] [среде] [у] LT', + '[прошлог] [четвртка] [у] LT', + '[прошлог] [петка] [у] LT', + '[прошле] [суботе] [у] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'за %s', + past : 'пре %s', + s : 'неколико секунди', + m : sr_cyrl__translator.translate, + mm : sr_cyrl__translator.translate, + h : sr_cyrl__translator.translate, + hh : sr_cyrl__translator.translate, + d : 'дан', + dd : sr_cyrl__translator.translate, + M : 'месец', + MM : sr_cyrl__translator.translate, + y : 'годину', + yy : sr_cyrl__translator.translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var sr__translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jedne minute'], + mm: ['minut', 'minute', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mesec', 'meseca', 'meseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = sr__translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + sr__translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var sr = moment__default.defineLocale('sr', { + months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays: 'nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota'.split('_'), + weekdaysShort: 'ned._pon._uto._sre._čet._pet._sub.'.split('_'), + weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm', + LTS : 'H:mm:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm', + LLLL: 'dddd, D. MMMM YYYY H:mm' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sutra u] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedelju] [u] LT'; + case 3: + return '[u] [sredu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedelje] [u] LT', + '[prošlog] [ponedeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'pre %s', + s : 'nekoliko sekundi', + m : sr__translator.translate, + mm : sr__translator.translate, + h : sr__translator.translate, + hh : sr__translator.translate, + d : 'dan', + dd : sr__translator.translate, + M : 'mesec', + MM : sr__translator.translate, + y : 'godinu', + yy : sr__translator.translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + + var ss = moment__default.defineLocale('ss', { + months : "Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split('_'), + monthsShort : 'Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo'.split('_'), + weekdays : 'Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo'.split('_'), + weekdaysShort : 'Lis_Umb_Lsb_Les_Lsi_Lsh_Umg'.split('_'), + weekdaysMin : 'Li_Us_Lb_Lt_Ls_Lh_Ug'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[Namuhla nga] LT', + nextDay : '[Kusasa nga] LT', + nextWeek : 'dddd [nga] LT', + lastDay : '[Itolo nga] LT', + lastWeek : 'dddd [leliphelile] [nga] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'nga %s', + past : 'wenteka nga %s', + s : 'emizuzwana lomcane', + m : 'umzuzu', + mm : '%d emizuzu', + h : 'lihora', + hh : '%d emahora', + d : 'lilanga', + dd : '%d emalanga', + M : 'inyanga', + MM : '%d tinyanga', + y : 'umnyaka', + yy : '%d iminyaka' + }, + meridiemParse: /ekuseni|emini|entsambama|ebusuku/, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'ekuseni'; + } else if (hours < 15) { + return 'emini'; + } else if (hours < 19) { + return 'entsambama'; + } else { + return 'ebusuku'; + } + }, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'ekuseni') { + return hour; + } else if (meridiem === 'emini') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'entsambama' || meridiem === 'ebusuku') { + if (hour === 0) { + return 0; + } + return hour + 12; + } + }, + ordinalParse: /\d{1,2}/, + ordinal : '%d', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var sv = moment__default.defineLocale('sv', { + months : 'januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december'.split('_'), + monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'), + weekdays : 'söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag'.split('_'), + weekdaysShort : 'sön_mån_tis_ons_tor_fre_lör'.split('_'), + weekdaysMin : 'sö_må_ti_on_to_fr_lö'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [kl.] HH:mm', + LLLL : 'dddd D MMMM YYYY [kl.] HH:mm', + lll : 'D MMM YYYY HH:mm', + llll : 'ddd D MMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Idag] LT', + nextDay: '[Imorgon] LT', + lastDay: '[Igår] LT', + nextWeek: '[På] dddd LT', + lastWeek: '[I] dddd[s] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : 'för %s sedan', + s : 'några sekunder', + m : 'en minut', + mm : '%d minuter', + h : 'en timme', + hh : '%d timmar', + d : 'en dag', + dd : '%d dagar', + M : 'en månad', + MM : '%d månader', + y : 'ett år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}(e|a)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'e' : + (b === 1) ? 'a' : + (b === 2) ? 'a' : + (b === 3) ? 'e' : 'e'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var sw = moment__default.defineLocale('sw', { + months : 'Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba'.split('_'), + monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi'.split('_'), + weekdaysShort : 'Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos'.split('_'), + weekdaysMin : 'J2_J3_J4_J5_Al_Ij_J1'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[leo saa] LT', + nextDay : '[kesho saa] LT', + nextWeek : '[wiki ijayo] dddd [saat] LT', + lastDay : '[jana] LT', + lastWeek : '[wiki iliyopita] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s baadaye', + past : 'tokea %s', + s : 'hivi punde', + m : 'dakika moja', + mm : 'dakika %d', + h : 'saa limoja', + hh : 'masaa %d', + d : 'siku moja', + dd : 'masiku %d', + M : 'mwezi mmoja', + MM : 'miezi %d', + y : 'mwaka mmoja', + yy : 'miaka %d' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var ta__symbolMap = { + '1': '௧', + '2': '௨', + '3': '௩', + '4': '௪', + '5': '௫', + '6': '௬', + '7': '௭', + '8': '௮', + '9': '௯', + '0': '௦' + }, ta__numberMap = { + '௧': '1', + '௨': '2', + '௩': '3', + '௪': '4', + '௫': '5', + '௬': '6', + '௭': '7', + '௮': '8', + '௯': '9', + '௦': '0' + }; + + var ta = moment__default.defineLocale('ta', { + months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'), + weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'), + weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, HH:mm', + LLLL : 'dddd, D MMMM YYYY, HH:mm' + }, + calendar : { + sameDay : '[இன்று] LT', + nextDay : '[நாளை] LT', + nextWeek : 'dddd, LT', + lastDay : '[நேற்று] LT', + lastWeek : '[கடந்த வாரம்] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s இல்', + past : '%s முன்', + s : 'ஒரு சில விநாடிகள்', + m : 'ஒரு நிமிடம்', + mm : '%d நிமிடங்கள்', + h : 'ஒரு மணி நேரம்', + hh : '%d மணி நேரம்', + d : 'ஒரு நாள்', + dd : '%d நாட்கள்', + M : 'ஒரு மாதம்', + MM : '%d மாதங்கள்', + y : 'ஒரு வருடம்', + yy : '%d ஆண்டுகள்' + }, + ordinalParse: /\d{1,2}வது/, + ordinal : function (number) { + return number + 'வது'; + }, + preparse: function (string) { + return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) { + return ta__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return ta__symbolMap[match]; + }); + }, + // refer http://ta.wikipedia.org/s/1er1 + meridiemParse: /யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/, + meridiem : function (hour, minute, isLower) { + if (hour < 2) { + return ' யாமம்'; + } else if (hour < 6) { + return ' வைகறை'; // வைகறை + } else if (hour < 10) { + return ' காலை'; // காலை + } else if (hour < 14) { + return ' நண்பகல்'; // நண்பகல் + } else if (hour < 18) { + return ' எற்பாடு'; // எற்பாடு + } else if (hour < 22) { + return ' மாலை'; // மாலை + } else { + return ' யாமம்'; + } + }, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'யாமம்') { + return hour < 2 ? hour : hour + 12; + } else if (meridiem === 'வைகறை' || meridiem === 'காலை') { + return hour; + } else if (meridiem === 'நண்பகல்') { + return hour >= 10 ? hour : hour + 12; + } else { + return hour + 12; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var te = moment__default.defineLocale('te', { + months : 'జనవరి_ఫిబ్రవరి_మార్చి_ఏప్రిల్_మే_జూన్_జూలై_ఆగస్టు_సెప్టెంబర్_అక్టోబర్_నవంబర్_డిసెంబర్'.split('_'), + monthsShort : 'జన._ఫిబ్ర._మార్చి_ఏప్రి._మే_జూన్_జూలై_ఆగ._సెప్._అక్టో._నవ._డిసె.'.split('_'), + monthsParseExact : true, + weekdays : 'ఆదివారం_సోమవారం_మంగళవారం_బుధవారం_గురువారం_శుక్రవారం_శనివారం'.split('_'), + weekdaysShort : 'ఆది_సోమ_మంగళ_బుధ_గురు_శుక్ర_శని'.split('_'), + weekdaysMin : 'ఆ_సో_మం_బు_గు_శు_శ'.split('_'), + longDateFormat : { + LT : 'A h:mm', + LTS : 'A h:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm', + LLLL : 'dddd, D MMMM YYYY, A h:mm' + }, + calendar : { + sameDay : '[నేడు] LT', + nextDay : '[రేపు] LT', + nextWeek : 'dddd, LT', + lastDay : '[నిన్న] LT', + lastWeek : '[గత] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s లో', + past : '%s క్రితం', + s : 'కొన్ని క్షణాలు', + m : 'ఒక నిమిషం', + mm : '%d నిమిషాలు', + h : 'ఒక గంట', + hh : '%d గంటలు', + d : 'ఒక రోజు', + dd : '%d రోజులు', + M : 'ఒక నెల', + MM : '%d నెలలు', + y : 'ఒక సంవత్సరం', + yy : '%d సంవత్సరాలు' + }, + ordinalParse : /\d{1,2}వ/, + ordinal : '%dవ', + meridiemParse: /రాత్రి|ఉదయం|మధ్యాహ్నం|సాయంత్రం/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'రాత్రి') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'ఉదయం') { + return hour; + } else if (meridiem === 'మధ్యాహ్నం') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'సాయంత్రం') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'రాత్రి'; + } else if (hour < 10) { + return 'ఉదయం'; + } else if (hour < 17) { + return 'మధ్యాహ్నం'; + } else if (hour < 20) { + return 'సాయంత్రం'; + } else { + return 'రాత్రి'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var th = moment__default.defineLocale('th', { + months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'), + monthsShort : 'ม.ค._ก.พ._มี.ค._เม.ย._พ.ค._มิ.ย._ก.ค._ส.ค._ก.ย._ต.ค._พ.ย._ธ.ค.'.split('_'), + monthsParseExact: true, + weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'), + weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference + weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H นาฬิกา m นาที', + LTS : 'H นาฬิกา m นาที s วินาที', + L : 'YYYY/MM/DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY เวลา H นาฬิกา m นาที', + LLLL : 'วันddddที่ D MMMM YYYY เวลา H นาฬิกา m นาที' + }, + meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/, + isPM: function (input) { + return input === 'หลังเที่ยง'; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ก่อนเที่ยง'; + } else { + return 'หลังเที่ยง'; + } + }, + calendar : { + sameDay : '[วันนี้ เวลา] LT', + nextDay : '[พรุ่งนี้ เวลา] LT', + nextWeek : 'dddd[หน้า เวลา] LT', + lastDay : '[เมื่อวานนี้ เวลา] LT', + lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'อีก %s', + past : '%sที่แล้ว', + s : 'ไม่กี่วินาที', + m : '1 นาที', + mm : '%d นาที', + h : '1 ชั่วโมง', + hh : '%d ชั่วโมง', + d : '1 วัน', + dd : '%d วัน', + M : '1 เดือน', + MM : '%d เดือน', + y : '1 ปี', + yy : '%d ปี' + } + }); + + + var tl_ph = moment__default.defineLocale('tl-ph', { + months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'), + monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'), + weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'), + weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'), + weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'MM/D/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY HH:mm', + LLLL : 'dddd, MMMM DD, YYYY HH:mm' + }, + calendar : { + sameDay: '[Ngayon sa] LT', + nextDay: '[Bukas sa] LT', + nextWeek: 'dddd [sa] LT', + lastDay: '[Kahapon sa] LT', + lastWeek: 'dddd [huling linggo] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'sa loob ng %s', + past : '%s ang nakalipas', + s : 'ilang segundo', + m : 'isang minuto', + mm : '%d minuto', + h : 'isang oras', + hh : '%d oras', + d : 'isang araw', + dd : '%d araw', + M : 'isang buwan', + MM : '%d buwan', + y : 'isang taon', + yy : '%d taon' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var numbersNouns = 'pagh_wa’_cha’_wej_loS_vagh_jav_Soch_chorgh_Hut'.split('_'); + + function translateFuture(output) { + var time = output; + time = (output.indexOf('jaj') !== -1) ? + time.slice(0, -3) + 'leS' : + (output.indexOf('jar') !== -1) ? + time.slice(0, -3) + 'waQ' : + (output.indexOf('DIS') !== -1) ? + time.slice(0, -3) + 'nem' : + time + ' pIq'; + return time; + } + + function translatePast(output) { + var time = output; + time = (output.indexOf('jaj') !== -1) ? + time.slice(0, -3) + 'Hu’' : + (output.indexOf('jar') !== -1) ? + time.slice(0, -3) + 'wen' : + (output.indexOf('DIS') !== -1) ? + time.slice(0, -3) + 'ben' : + time + ' ret'; + return time; + } + + function tlh__translate(number, withoutSuffix, string, isFuture) { + var numberNoun = numberAsNoun(number); + switch (string) { + case 'mm': + return numberNoun + ' tup'; + case 'hh': + return numberNoun + ' rep'; + case 'dd': + return numberNoun + ' jaj'; + case 'MM': + return numberNoun + ' jar'; + case 'yy': + return numberNoun + ' DIS'; + } + } + + function numberAsNoun(number) { + var hundred = Math.floor((number % 1000) / 100), + ten = Math.floor((number % 100) / 10), + one = number % 10, + word = ''; + if (hundred > 0) { + word += numbersNouns[hundred] + 'vatlh'; + } + if (ten > 0) { + word += ((word !== '') ? ' ' : '') + numbersNouns[ten] + 'maH'; + } + if (one > 0) { + word += ((word !== '') ? ' ' : '') + numbersNouns[one]; + } + return (word === '') ? 'pagh' : word; + } + + var tlh = moment__default.defineLocale('tlh', { + months : 'tera’ jar wa’_tera’ jar cha’_tera’ jar wej_tera’ jar loS_tera’ jar vagh_tera’ jar jav_tera’ jar Soch_tera’ jar chorgh_tera’ jar Hut_tera’ jar wa’maH_tera’ jar wa’maH wa’_tera’ jar wa’maH cha’'.split('_'), + monthsShort : 'jar wa’_jar cha’_jar wej_jar loS_jar vagh_jar jav_jar Soch_jar chorgh_jar Hut_jar wa’maH_jar wa’maH wa’_jar wa’maH cha’'.split('_'), + monthsParseExact : true, + weekdays : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'), + weekdaysShort : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'), + weekdaysMin : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[DaHjaj] LT', + nextDay: '[wa’leS] LT', + nextWeek: 'LLL', + lastDay: '[wa’Hu’] LT', + lastWeek: 'LLL', + sameElse: 'L' + }, + relativeTime : { + future : translateFuture, + past : translatePast, + s : 'puS lup', + m : 'wa’ tup', + mm : tlh__translate, + h : 'wa’ rep', + hh : tlh__translate, + d : 'wa’ jaj', + dd : tlh__translate, + M : 'wa’ jar', + MM : tlh__translate, + y : 'wa’ DIS', + yy : tlh__translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var tr__suffixes = { + 1: '\'inci', + 5: '\'inci', + 8: '\'inci', + 70: '\'inci', + 80: '\'inci', + 2: '\'nci', + 7: '\'nci', + 20: '\'nci', + 50: '\'nci', + 3: '\'üncü', + 4: '\'üncü', + 100: '\'üncü', + 6: '\'ncı', + 9: '\'uncu', + 10: '\'uncu', + 30: '\'uncu', + 60: '\'ıncı', + 90: '\'ıncı' + }; + + var tr = moment__default.defineLocale('tr', { + months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'), + monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'), + weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'), + weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'), + weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[bugün saat] LT', + nextDay : '[yarın saat] LT', + nextWeek : '[haftaya] dddd [saat] LT', + lastDay : '[dün] LT', + lastWeek : '[geçen hafta] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s sonra', + past : '%s önce', + s : 'birkaç saniye', + m : 'bir dakika', + mm : '%d dakika', + h : 'bir saat', + hh : '%d saat', + d : 'bir gün', + dd : '%d gün', + M : 'bir ay', + MM : '%d ay', + y : 'bir yıl', + yy : '%d yıl' + }, + ordinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/, + ordinal : function (number) { + if (number === 0) { // special case for zero + return number + '\'ıncı'; + } + var a = number % 10, + b = number % 100 - a, + c = number >= 100 ? 100 : null; + return number + (tr__suffixes[a] || tr__suffixes[b] || tr__suffixes[c]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + + // After the year there should be a slash and the amount of years since December 26, 1979 in Roman numerals. + // This is currently too difficult (maybe even impossible) to add. + var tzl = moment__default.defineLocale('tzl', { + months : 'Januar_Fevraglh_Març_Avrïu_Mai_Gün_Julia_Guscht_Setemvar_Listopäts_Noemvar_Zecemvar'.split('_'), + monthsShort : 'Jan_Fev_Mar_Avr_Mai_Gün_Jul_Gus_Set_Lis_Noe_Zec'.split('_'), + weekdays : 'Súladi_Lúneçi_Maitzi_Márcuri_Xhúadi_Viénerçi_Sáturi'.split('_'), + weekdaysShort : 'Súl_Lún_Mai_Már_Xhú_Vié_Sát'.split('_'), + weekdaysMin : 'Sú_Lú_Ma_Má_Xh_Vi_Sá'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM [dallas] YYYY', + LLL : 'D. MMMM [dallas] YYYY HH.mm', + LLLL : 'dddd, [li] D. MMMM [dallas] YYYY HH.mm' + }, + meridiemParse: /d\'o|d\'a/i, + isPM : function (input) { + return 'd\'o' === input.toLowerCase(); + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'd\'o' : 'D\'O'; + } else { + return isLower ? 'd\'a' : 'D\'A'; + } + }, + calendar : { + sameDay : '[oxhi à] LT', + nextDay : '[demà à] LT', + nextWeek : 'dddd [à] LT', + lastDay : '[ieiri à] LT', + lastWeek : '[sür el] dddd [lasteu à] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'osprei %s', + past : 'ja%s', + s : tzl__processRelativeTime, + m : tzl__processRelativeTime, + mm : tzl__processRelativeTime, + h : tzl__processRelativeTime, + hh : tzl__processRelativeTime, + d : tzl__processRelativeTime, + dd : tzl__processRelativeTime, + M : tzl__processRelativeTime, + MM : tzl__processRelativeTime, + y : tzl__processRelativeTime, + yy : tzl__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + function tzl__processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 's': ['viensas secunds', '\'iensas secunds'], + 'm': ['\'n míut', '\'iens míut'], + 'mm': [number + ' míuts', '' + number + ' míuts'], + 'h': ['\'n þora', '\'iensa þora'], + 'hh': [number + ' þoras', '' + number + ' þoras'], + 'd': ['\'n ziua', '\'iensa ziua'], + 'dd': [number + ' ziuas', '' + number + ' ziuas'], + 'M': ['\'n mes', '\'iens mes'], + 'MM': [number + ' mesen', '' + number + ' mesen'], + 'y': ['\'n ar', '\'iens ar'], + 'yy': [number + ' ars', '' + number + ' ars'] + }; + return isFuture ? format[key][0] : (withoutSuffix ? format[key][0] : format[key][1]); + } + + + var tzm_latn = moment__default.defineLocale('tzm-latn', { + months : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'), + monthsShort : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'), + weekdays : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), + weekdaysShort : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), + weekdaysMin : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[asdkh g] LT', + nextDay: '[aska g] LT', + nextWeek: 'dddd [g] LT', + lastDay: '[assant g] LT', + lastWeek: 'dddd [g] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dadkh s yan %s', + past : 'yan %s', + s : 'imik', + m : 'minuḍ', + mm : '%d minuḍ', + h : 'saɛa', + hh : '%d tassaɛin', + d : 'ass', + dd : '%d ossan', + M : 'ayowr', + MM : '%d iyyirn', + y : 'asgas', + yy : '%d isgasn' + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var tzm = moment__default.defineLocale('tzm', { + months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[ⴰⵙⴷⵅ ⴴ] LT', + nextDay: '[ⴰⵙⴽⴰ ⴴ] LT', + nextWeek: 'dddd [ⴴ] LT', + lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT', + lastWeek: 'dddd [ⴴ] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s', + past : 'ⵢⴰⵏ %s', + s : 'ⵉⵎⵉⴽ', + m : 'ⵎⵉⵏⵓⴺ', + mm : '%d ⵎⵉⵏⵓⴺ', + h : 'ⵙⴰⵄⴰ', + hh : '%d ⵜⴰⵙⵙⴰⵄⵉⵏ', + d : 'ⴰⵙⵙ', + dd : '%d oⵙⵙⴰⵏ', + M : 'ⴰⵢoⵓⵔ', + MM : '%d ⵉⵢⵢⵉⵔⵏ', + y : 'ⴰⵙⴳⴰⵙ', + yy : '%d ⵉⵙⴳⴰⵙⵏ' + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } + }); + + + function uk__plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); + } + function uk__relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'хвилина_хвилини_хвилин' : 'хвилину_хвилини_хвилин', + 'hh': withoutSuffix ? 'година_години_годин' : 'годину_години_годин', + 'dd': 'день_дні_днів', + 'MM': 'місяць_місяці_місяців', + 'yy': 'рік_роки_років' + }; + if (key === 'm') { + return withoutSuffix ? 'хвилина' : 'хвилину'; + } + else if (key === 'h') { + return withoutSuffix ? 'година' : 'годину'; + } + else { + return number + ' ' + uk__plural(format[key], +number); + } + } + function weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'), + 'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'), + 'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_') + }, + nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ? + 'accusative' : + ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ? + 'genitive' : + 'nominative'); + return weekdays[nounCase][m.day()]; + } + function processHoursFunction(str) { + return function () { + return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT'; + }; + } + + var uk = moment__default.defineLocale('uk', { + months : { + 'format': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_'), + 'standalone': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_') + }, + monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'), + weekdays : weekdaysCaseReplace, + weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY р.', + LLL : 'D MMMM YYYY р., HH:mm', + LLLL : 'dddd, D MMMM YYYY р., HH:mm' + }, + calendar : { + sameDay: processHoursFunction('[Сьогодні '), + nextDay: processHoursFunction('[Завтра '), + lastDay: processHoursFunction('[Вчора '), + nextWeek: processHoursFunction('[У] dddd ['), + lastWeek: function () { + switch (this.day()) { + case 0: + case 3: + case 5: + case 6: + return processHoursFunction('[Минулої] dddd [').call(this); + case 1: + case 2: + case 4: + return processHoursFunction('[Минулого] dddd [').call(this); + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'за %s', + past : '%s тому', + s : 'декілька секунд', + m : uk__relativeTimeWithPlural, + mm : uk__relativeTimeWithPlural, + h : 'годину', + hh : uk__relativeTimeWithPlural, + d : 'день', + dd : uk__relativeTimeWithPlural, + M : 'місяць', + MM : uk__relativeTimeWithPlural, + y : 'рік', + yy : uk__relativeTimeWithPlural + }, + // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason + meridiemParse: /ночі|ранку|дня|вечора/, + isPM: function (input) { + return /^(дня|вечора)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночі'; + } else if (hour < 12) { + return 'ранку'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечора'; + } + }, + ordinalParse: /\d{1,2}-(й|го)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + case 'w': + case 'W': + return number + '-й'; + case 'D': + return number + '-го'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } + }); + + + var uz = moment__default.defineLocale('uz', { + months : 'январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр'.split('_'), + monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'), + weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'), + weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'), + weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'D MMMM YYYY, dddd HH:mm' + }, + calendar : { + sameDay : '[Бугун соат] LT [да]', + nextDay : '[Эртага] LT [да]', + nextWeek : 'dddd [куни соат] LT [да]', + lastDay : '[Кеча соат] LT [да]', + lastWeek : '[Утган] dddd [куни соат] LT [да]', + sameElse : 'L' + }, + relativeTime : { + future : 'Якин %s ичида', + past : 'Бир неча %s олдин', + s : 'фурсат', + m : 'бир дакика', + mm : '%d дакика', + h : 'бир соат', + hh : '%d соат', + d : 'бир кун', + dd : '%d кун', + M : 'бир ой', + MM : '%d ой', + y : 'бир йил', + yy : '%d йил' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var vi = moment__default.defineLocale('vi', { + months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'), + monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'), + monthsParseExact : true, + weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'), + weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + weekdaysParseExact : true, + meridiemParse: /sa|ch/i, + isPM : function (input) { + return /^ch$/i.test(input); + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower ? 'sa' : 'SA'; + } else { + return isLower ? 'ch' : 'CH'; + } + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM [năm] YYYY', + LLL : 'D MMMM [năm] YYYY HH:mm', + LLLL : 'dddd, D MMMM [năm] YYYY HH:mm', + l : 'DD/M/YYYY', + ll : 'D MMM YYYY', + lll : 'D MMM YYYY HH:mm', + llll : 'ddd, D MMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Hôm nay lúc] LT', + nextDay: '[Ngày mai lúc] LT', + nextWeek: 'dddd [tuần tới lúc] LT', + lastDay: '[Hôm qua lúc] LT', + lastWeek: 'dddd [tuần rồi lúc] LT', + sameElse: 'L' + }, + relativeTime : { + future : '%s tới', + past : '%s trước', + s : 'vài giây', + m : 'một phút', + mm : '%d phút', + h : 'một giờ', + hh : '%d giờ', + d : 'một ngày', + dd : '%d ngày', + M : 'một tháng', + MM : '%d tháng', + y : 'một năm', + yy : '%d năm' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var x_pseudo = moment__default.defineLocale('x-pseudo', { + months : 'J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér'.split('_'), + monthsShort : 'J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc'.split('_'), + monthsParseExact : true, + weekdays : 'S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý'.split('_'), + weekdaysShort : 'S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát'.split('_'), + weekdaysMin : 'S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[T~ódá~ý át] LT', + nextDay : '[T~ómó~rró~w át] LT', + nextWeek : 'dddd [át] LT', + lastDay : '[Ý~ést~érdá~ý át] LT', + lastWeek : '[L~ást] dddd [át] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'í~ñ %s', + past : '%s á~gó', + s : 'á ~féw ~sécó~ñds', + m : 'á ~míñ~úté', + mm : '%d m~íñú~tés', + h : 'á~ñ hó~úr', + hh : '%d h~óúrs', + d : 'á ~dáý', + dd : '%d d~áýs', + M : 'á ~móñ~th', + MM : '%d m~óñt~hs', + y : 'á ~ýéár', + yy : '%d ý~éárs' + }, + ordinalParse: /\d{1,2}(th|st|nd|rd)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var zh_cn = moment__default.defineLocale('zh-cn', { + months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'), + monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'), + weekdaysShort : '周日_周一_周二_周三_周四_周五_周六'.split('_'), + weekdaysMin : '日_一_二_三_四_五_六'.split('_'), + longDateFormat : { + LT : 'Ah点mm分', + LTS : 'Ah点m分s秒', + L : 'YYYY-MM-DD', + LL : 'YYYY年MMMD日', + LLL : 'YYYY年MMMD日Ah点mm分', + LLLL : 'YYYY年MMMD日ddddAh点mm分', + l : 'YYYY-MM-DD', + ll : 'YYYY年MMMD日', + lll : 'YYYY年MMMD日Ah点mm分', + llll : 'YYYY年MMMD日ddddAh点mm分' + }, + meridiemParse: /凌晨|早上|上午|中午|下午|晚上/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '凌晨' || meridiem === '早上' || + meridiem === '上午') { + return hour; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } else { + // '中午' + return hour >= 11 ? hour : hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 600) { + return '凌晨'; + } else if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : function () { + return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT'; + }, + nextDay : function () { + return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT'; + }, + lastDay : function () { + return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT'; + }, + nextWeek : function () { + var startOfWeek, prefix; + startOfWeek = moment__default().startOf('week'); + prefix = this.diff(startOfWeek, 'days') >= 7 ? '[下]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + lastWeek : function () { + var startOfWeek, prefix; + startOfWeek = moment__default().startOf('week'); + prefix = this.unix() < startOfWeek.unix() ? '[上]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + sameElse : 'LL' + }, + ordinalParse: /\d{1,2}(日|月|周)/, + ordinal : function (number, period) { + switch (period) { + case 'd': + case 'D': + case 'DDD': + return number + '日'; + case 'M': + return number + '月'; + case 'w': + case 'W': + return number + '周'; + default: + return number; + } + }, + relativeTime : { + future : '%s内', + past : '%s前', + s : '几秒', + m : '1 分钟', + mm : '%d 分钟', + h : '1 小时', + hh : '%d 小时', + d : '1 天', + dd : '%d 天', + M : '1 个月', + MM : '%d 个月', + y : '1 年', + yy : '%d 年' + }, + week : { + // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效 + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + + var zh_tw = moment__default.defineLocale('zh-tw', { + months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'), + monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'), + weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'), + weekdaysMin : '日_一_二_三_四_五_六'.split('_'), + longDateFormat : { + LT : 'Ah點mm分', + LTS : 'Ah點m分s秒', + L : 'YYYY年MMMD日', + LL : 'YYYY年MMMD日', + LLL : 'YYYY年MMMD日Ah點mm分', + LLLL : 'YYYY年MMMD日ddddAh點mm分', + l : 'YYYY年MMMD日', + ll : 'YYYY年MMMD日', + lll : 'YYYY年MMMD日Ah點mm分', + llll : 'YYYY年MMMD日ddddAh點mm分' + }, + meridiemParse: /凌晨|早上|上午|中午|下午|晚上/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') { + return hour; + } else if (meridiem === '中午') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 600) { + return '凌晨'; + } else if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : '[今天]LT', + nextDay : '[明天]LT', + nextWeek : '[下]ddddLT', + lastDay : '[昨天]LT', + lastWeek : '[上]ddddLT', + sameElse : 'L' + }, + ordinalParse: /\d{1,2}(日|月|週)/, + ordinal : function (number, period) { + switch (period) { + case 'd' : + case 'D' : + case 'DDD' : + return number + '日'; + case 'M' : + return number + '月'; + case 'w' : + case 'W' : + return number + '週'; + default : + return number; + } + }, + relativeTime : { + future : '%s內', + past : '%s前', + s : '幾秒', + m : '1 分鐘', + mm : '%d 分鐘', + h : '1 小時', + hh : '%d 小時', + d : '1 天', + dd : '%d 天', + M : '1 個月', + MM : '%d 個月', + y : '1 年', + yy : '%d 年' + } + }); + + var moment_with_locales = moment__default; + moment_with_locales.locale('en'); + + return moment_with_locales; + +}));
@@ -0,0 +1,673 @@
+//! moment.js +//! version : 2.14.1 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com +!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return je.apply(null,arguments)} +// This is done to register the method called with moment() +// without creating circular dependencies. +function b(a){je=a}function c(a){return a instanceof Array||"[object Array]"===Object.prototype.toString.call(a)}function d(a){return"[object Object]"===Object.prototype.toString.call(a)}function e(a){var b;for(b in a) +// even if its not own property I'd still call it non-empty +return!1;return!0}function f(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function g(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function h(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function i(a,b){for(var c in b)h(b,c)&&(a[c]=b[c]);return h(b,"toString")&&(a.toString=b.toString),h(b,"valueOf")&&(a.valueOf=b.valueOf),a}function j(a,b,c,d){return qb(a,b,c,d,!0).utc()}function k(){ +// We need to deep clone this object. +return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null}}function l(a){return null==a._pf&&(a._pf=k()),a._pf}function m(a){if(null==a._isValid){var b=l(a),c=ke.call(b.parsedDateParts,function(a){return null!=a});a._isValid=!isNaN(a._d.getTime())&&b.overflow<0&&!b.empty&&!b.invalidMonth&&!b.invalidWeekday&&!b.nullInput&&!b.invalidFormat&&!b.userInvalidated&&(!b.meridiem||b.meridiem&&c),a._strict&&(a._isValid=a._isValid&&0===b.charsLeftOver&&0===b.unusedTokens.length&&void 0===b.bigHour)}return a._isValid}function n(a){var b=j(NaN);return null!=a?i(l(b),a):l(b).userInvalidated=!0,b}function o(a){return void 0===a}function p(a,b){var c,d,e;if(o(b._isAMomentObject)||(a._isAMomentObject=b._isAMomentObject),o(b._i)||(a._i=b._i),o(b._f)||(a._f=b._f),o(b._l)||(a._l=b._l),o(b._strict)||(a._strict=b._strict),o(b._tzm)||(a._tzm=b._tzm),o(b._isUTC)||(a._isUTC=b._isUTC),o(b._offset)||(a._offset=b._offset),o(b._pf)||(a._pf=l(b)),o(b._locale)||(a._locale=b._locale),le.length>0)for(c in le)d=le[c],e=b[d],o(e)||(a[d]=e);return a} +// Moment prototype object +function q(b){p(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),me===!1&&(me=!0,a.updateOffset(this),me=!1)}function r(a){return a instanceof q||null!=a&&null!=a._isAMomentObject}function s(a){return 0>a?Math.ceil(a)||0:Math.floor(a)}function t(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=s(b)),c} +// compare two arrays, return the number of differences +function u(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&t(a[d])!==t(b[d]))&&g++;return g+f}function v(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function w(b,c){var d=!0;return i(function(){return null!=a.deprecationHandler&&a.deprecationHandler(null,b),d&&(v(b+"\nArguments: "+Array.prototype.slice.call(arguments).join(", ")+"\n"+(new Error).stack),d=!1),c.apply(this,arguments)},c)}function x(b,c){null!=a.deprecationHandler&&a.deprecationHandler(b,c),ne[b]||(v(c),ne[b]=!0)}function y(a){return a instanceof Function||"[object Function]"===Object.prototype.toString.call(a)}function z(a){var b,c;for(c in a)b=a[c],y(b)?this[c]=b:this["_"+c]=b;this._config=a, +// Lenient ordinal parsing accepts just a number in addition to +// number + (possibly) stuff coming from _ordinalParseLenient. +this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function A(a,b){var c,e=i({},a);for(c in b)h(b,c)&&(d(a[c])&&d(b[c])?(e[c]={},i(e[c],a[c]),i(e[c],b[c])):null!=b[c]?e[c]=b[c]:delete e[c]);for(c in a)h(a,c)&&!h(b,c)&&d(a[c])&&( +// make sure changes to properties don't modify parent config +e[c]=i({},e[c]));return e}function B(a){null!=a&&this.set(a)}function C(a,b,c){var d=this._calendar[a]||this._calendar.sameElse;return y(d)?d.call(b,c):d}function D(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function E(){return this._invalidDate}function F(a){return this._ordinal.replace("%d",a)}function G(a,b,c,d){var e=this._relativeTime[c];return y(e)?e(a,b,c,d):e.replace(/%d/i,a)}function H(a,b){var c=this._relativeTime[a>0?"future":"past"];return y(c)?c(b):c.replace(/%s/i,b)}function I(a,b){var c=a.toLowerCase();we[c]=we[c+"s"]=we[b]=a}function J(a){return"string"==typeof a?we[a]||we[a.toLowerCase()]:void 0}function K(a){var b,c,d={};for(c in a)h(a,c)&&(b=J(c),b&&(d[b]=a[c]));return d}function L(a,b){xe[a]=b}function M(a){var b=[];for(var c in a)b.push({unit:c,priority:xe[c]});return b.sort(function(a,b){return a.priority-b.priority}),b}function N(b,c){return function(d){return null!=d?(P(this,b,d),a.updateOffset(this,c),this):O(this,b)}}function O(a,b){return a.isValid()?a._d["get"+(a._isUTC?"UTC":"")+b]():NaN}function P(a,b,c){a.isValid()&&a._d["set"+(a._isUTC?"UTC":"")+b](c)} +// MOMENTS +function Q(a){return a=J(a),y(this[a])?this[a]():this}function R(a,b){if("object"==typeof a){a=K(a);for(var c=M(a),d=0;d<c.length;d++)this[c[d].unit](a[c[d].unit])}else if(a=J(a),y(this[a]))return this[a](b);return this}function S(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d} +// token: 'M' +// padded: ['MM', 2] +// ordinal: 'Mo' +// callback: function () { this.month() + 1 } +function T(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Be[a]=e),b&&(Be[b[0]]=function(){return S(e.apply(this,arguments),b[1],b[2])}),c&&(Be[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function U(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function V(a){var b,c,d=a.match(ye);for(b=0,c=d.length;c>b;b++)Be[d[b]]?d[b]=Be[d[b]]:d[b]=U(d[b]);return function(b){var e,f="";for(e=0;c>e;e++)f+=d[e]instanceof Function?d[e].call(b,a):d[e];return f}} +// format date using native date object +function W(a,b){return a.isValid()?(b=X(b,a.localeData()),Ae[b]=Ae[b]||V(b),Ae[b](a)):a.localeData().invalidDate()}function X(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(ze.lastIndex=0;d>=0&&ze.test(a);)a=a.replace(ze,c),ze.lastIndex=0,d-=1;return a}function Y(a,b,c){Te[a]=y(b)?b:function(a,d){return a&&c?c:b}}function Z(a,b){return h(Te,a)?Te[a](b._strict,b._locale):new RegExp($(a))} +// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript +function $(a){return _(a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}))}function _(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function aa(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=t(a)}),c=0;c<a.length;c++)Ue[a[c]]=d}function ba(a,b){aa(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}function ca(a,b,c){null!=b&&h(Ue,a)&&Ue[a](b,c._a,c,a)}function da(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function ea(a,b){return c(this._months)?this._months[a.month()]:this._months[(this._months.isFormat||cf).test(b)?"format":"standalone"][a.month()]}function fa(a,b){return c(this._monthsShort)?this._monthsShort[a.month()]:this._monthsShort[cf.test(b)?"format":"standalone"][a.month()]}function ga(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._monthsParse)for( +// this is not used +this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],d=0;12>d;++d)f=j([2e3,d]),this._shortMonthsParse[d]=this.monthsShort(f,"").toLocaleLowerCase(),this._longMonthsParse[d]=this.months(f,"").toLocaleLowerCase();return c?"MMM"===b?(e=pe.call(this._shortMonthsParse,g),-1!==e?e:null):(e=pe.call(this._longMonthsParse,g),-1!==e?e:null):"MMM"===b?(e=pe.call(this._shortMonthsParse,g),-1!==e?e:(e=pe.call(this._longMonthsParse,g),-1!==e?e:null)):(e=pe.call(this._longMonthsParse,g),-1!==e?e:(e=pe.call(this._shortMonthsParse,g),-1!==e?e:null))}function ha(a,b,c){var d,e,f;if(this._monthsParseExact)return ga.call(this,a,b,c); +// TODO: add sorting +// Sorting makes sure if one month (or abbr) is a prefix of another +// see sorting in computeMonthsParse +for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;12>d;d++){ +// test the regex +if(e=j([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}} +// MOMENTS +function ia(a,b){var c;if(!a.isValid()) +// No op +return a;if("string"==typeof b)if(/^\d+$/.test(b))b=t(b);else +// TODO: Another silent failure? +if(b=a.localeData().monthsParse(b),"number"!=typeof b)return a;return c=Math.min(a.date(),da(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a}function ja(b){return null!=b?(ia(this,b),a.updateOffset(this,!0),this):O(this,"Month")}function ka(){return da(this.year(),this.month())}function la(a){return this._monthsParseExact?(h(this,"_monthsRegex")||na.call(this),a?this._monthsShortStrictRegex:this._monthsShortRegex):(h(this,"_monthsShortRegex")||(this._monthsShortRegex=ff),this._monthsShortStrictRegex&&a?this._monthsShortStrictRegex:this._monthsShortRegex)}function ma(a){return this._monthsParseExact?(h(this,"_monthsRegex")||na.call(this),a?this._monthsStrictRegex:this._monthsRegex):(h(this,"_monthsRegex")||(this._monthsRegex=gf),this._monthsStrictRegex&&a?this._monthsStrictRegex:this._monthsRegex)}function na(){function a(a,b){return b.length-a.length}var b,c,d=[],e=[],f=[];for(b=0;12>b;b++)c=j([2e3,b]),d.push(this.monthsShort(c,"")),e.push(this.months(c,"")),f.push(this.months(c,"")),f.push(this.monthsShort(c,""));for( +// Sorting makes sure if one month (or abbr) is a prefix of another it +// will match the longer piece. +d.sort(a),e.sort(a),f.sort(a),b=0;12>b;b++)d[b]=_(d[b]),e[b]=_(e[b]);for(b=0;24>b;b++)f[b]=_(f[b]);this._monthsRegex=new RegExp("^("+f.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+e.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+d.join("|")+")","i")} +// HELPERS +function oa(a){return pa(a)?366:365}function pa(a){return a%4===0&&a%100!==0||a%400===0}function qa(){return pa(this.year())}function ra(a,b,c,d,e,f,g){ +//can't just apply() to create a date: +//http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply +var h=new Date(a,b,c,d,e,f,g); +//the date constructor remaps years 0-99 to 1900-1999 +return 100>a&&a>=0&&isFinite(h.getFullYear())&&h.setFullYear(a),h}function sa(a){var b=new Date(Date.UTC.apply(null,arguments)); +//the Date.UTC function remaps years 0-99 to 1900-1999 +return 100>a&&a>=0&&isFinite(b.getUTCFullYear())&&b.setUTCFullYear(a),b} +// start-of-first-week - start-of-year +function ta(a,b,c){var// first-week day -- which january is always in the first week (4 for iso, 1 for other) +d=7+b-c, +// first-week day local weekday -- which local weekday is fwd +e=(7+sa(a,0,d).getUTCDay()-b)%7;return-e+d-1} +//http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday +function ua(a,b,c,d,e){var f,g,h=(7+c-d)%7,i=ta(a,d,e),j=1+7*(b-1)+h+i;return 0>=j?(f=a-1,g=oa(f)+j):j>oa(a)?(f=a+1,g=j-oa(a)):(f=a,g=j),{year:f,dayOfYear:g}}function va(a,b,c){var d,e,f=ta(a.year(),b,c),g=Math.floor((a.dayOfYear()-f-1)/7)+1;return 1>g?(e=a.year()-1,d=g+wa(e,b,c)):g>wa(a.year(),b,c)?(d=g-wa(a.year(),b,c),e=a.year()+1):(e=a.year(),d=g),{week:d,year:e}}function wa(a,b,c){var d=ta(a,b,c),e=ta(a+1,b,c);return(oa(a)-d+e)/7} +// HELPERS +// LOCALES +function xa(a){return va(a,this._week.dow,this._week.doy).week}function ya(){return this._week.dow}function za(){return this._week.doy} +// MOMENTS +function Aa(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function Ba(a){var b=va(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")} +// HELPERS +function Ca(a,b){return"string"!=typeof a?a:isNaN(a)?(a=b.weekdaysParse(a),"number"==typeof a?a:null):parseInt(a,10)}function Da(a,b){return"string"==typeof a?b.weekdaysParse(a)%7||7:isNaN(a)?null:a}function Ea(a,b){return c(this._weekdays)?this._weekdays[a.day()]:this._weekdays[this._weekdays.isFormat.test(b)?"format":"standalone"][a.day()]}function Fa(a){return this._weekdaysShort[a.day()]}function Ga(a){return this._weekdaysMin[a.day()]}function Ha(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],d=0;7>d;++d)f=j([2e3,1]).day(d),this._minWeekdaysParse[d]=this.weekdaysMin(f,"").toLocaleLowerCase(),this._shortWeekdaysParse[d]=this.weekdaysShort(f,"").toLocaleLowerCase(),this._weekdaysParse[d]=this.weekdays(f,"").toLocaleLowerCase();return c?"dddd"===b?(e=pe.call(this._weekdaysParse,g),-1!==e?e:null):"ddd"===b?(e=pe.call(this._shortWeekdaysParse,g),-1!==e?e:null):(e=pe.call(this._minWeekdaysParse,g),-1!==e?e:null):"dddd"===b?(e=pe.call(this._weekdaysParse,g),-1!==e?e:(e=pe.call(this._shortWeekdaysParse,g),-1!==e?e:(e=pe.call(this._minWeekdaysParse,g),-1!==e?e:null))):"ddd"===b?(e=pe.call(this._shortWeekdaysParse,g),-1!==e?e:(e=pe.call(this._weekdaysParse,g),-1!==e?e:(e=pe.call(this._minWeekdaysParse,g),-1!==e?e:null))):(e=pe.call(this._minWeekdaysParse,g),-1!==e?e:(e=pe.call(this._weekdaysParse,g),-1!==e?e:(e=pe.call(this._shortWeekdaysParse,g),-1!==e?e:null)))}function Ia(a,b,c){var d,e,f;if(this._weekdaysParseExact)return Ha.call(this,a,b,c);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),d=0;7>d;d++){ +// test the regex +if(e=j([2e3,1]).day(d),c&&!this._fullWeekdaysParse[d]&&(this._fullWeekdaysParse[d]=new RegExp("^"+this.weekdays(e,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[d]=new RegExp("^"+this.weekdaysShort(e,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[d]=new RegExp("^"+this.weekdaysMin(e,"").replace(".",".?")+"$","i")),this._weekdaysParse[d]||(f="^"+this.weekdays(e,"")+"|^"+this.weekdaysShort(e,"")+"|^"+this.weekdaysMin(e,""),this._weekdaysParse[d]=new RegExp(f.replace(".",""),"i")),c&&"dddd"===b&&this._fullWeekdaysParse[d].test(a))return d;if(c&&"ddd"===b&&this._shortWeekdaysParse[d].test(a))return d;if(c&&"dd"===b&&this._minWeekdaysParse[d].test(a))return d;if(!c&&this._weekdaysParse[d].test(a))return d}} +// MOMENTS +function Ja(a){if(!this.isValid())return null!=a?this:NaN;var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Ca(a,this.localeData()),this.add(a-b,"d")):b}function Ka(a){if(!this.isValid())return null!=a?this:NaN;var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function La(a){if(!this.isValid())return null!=a?this:NaN; +// behaves the same as moment#day except +// as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) +// as a setter, sunday should belong to the previous week. +if(null!=a){var b=Da(a,this.localeData());return this.day(this.day()%7?b:b-7)}return this.day()||7}function Ma(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysStrictRegex:this._weekdaysRegex):(h(this,"_weekdaysRegex")||(this._weekdaysRegex=nf),this._weekdaysStrictRegex&&a?this._weekdaysStrictRegex:this._weekdaysRegex)}function Na(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(h(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=of),this._weekdaysShortStrictRegex&&a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Oa(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(h(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=pf),this._weekdaysMinStrictRegex&&a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Pa(){function a(a,b){return b.length-a.length}var b,c,d,e,f,g=[],h=[],i=[],k=[];for(b=0;7>b;b++)c=j([2e3,1]).day(b),d=this.weekdaysMin(c,""),e=this.weekdaysShort(c,""),f=this.weekdays(c,""),g.push(d),h.push(e),i.push(f),k.push(d),k.push(e),k.push(f);for( +// Sorting makes sure if one weekday (or abbr) is a prefix of another it +// will match the longer piece. +g.sort(a),h.sort(a),i.sort(a),k.sort(a),b=0;7>b;b++)h[b]=_(h[b]),i[b]=_(i[b]),k[b]=_(k[b]);this._weekdaysRegex=new RegExp("^("+k.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+h.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+g.join("|")+")","i")} +// FORMATTING +function Qa(){return this.hours()%12||12}function Ra(){return this.hours()||24}function Sa(a,b){T(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})} +// PARSING +function Ta(a,b){return b._meridiemParse} +// LOCALES +function Ua(a){ +// IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays +// Using charAt should be more compatible. +return"p"===(a+"").toLowerCase().charAt(0)}function Va(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Wa(a){return a?a.toLowerCase().replace("_","-"):a} +// pick the locale from the array +// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each +// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root +function Xa(a){for(var b,c,d,e,f=0;f<a.length;){for(e=Wa(a[f]).split("-"),b=e.length,c=Wa(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=Ya(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&u(e,c,!0)>=b-1) +//the next array item is better than a shallower substring of this one +break;b--}f++}return null}function Ya(a){var b=null; +// TODO: Find a better way to register and load all the locales in Node +if(!uf[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=qf._abbr,require("./locale/"+a), +// because defineLocale currently also sets the global locale, we +// want to undo that for lazy loaded locales +Za(b)}catch(c){}return uf[a]} +// This function will load locale and then set the global locale. If +// no arguments are passed in, it will simply return the current global +// locale key. +function Za(a,b){var c; +// moment.duration._locale = moment._locale = data; +return a&&(c=o(b)?ab(a):$a(a,b),c&&(qf=c)),qf._abbr}function $a(a,b){if(null!==b){var c=tf; +// treat as if there is no base config +// backwards compat for now: also set the locale +return b.abbr=a,null!=uf[a]?(x("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),c=uf[a]._config):null!=b.parentLocale&&(null!=uf[b.parentLocale]?c=uf[b.parentLocale]._config:x("parentLocaleUndefined","specified parentLocale is not defined yet. See http://momentjs.com/guides/#/warnings/parent-locale/")),uf[a]=new B(A(c,b)),Za(a),uf[a]} +// useful for testing +return delete uf[a],null}function _a(a,b){if(null!=b){var c,d=tf; +// MERGE +null!=uf[a]&&(d=uf[a]._config),b=A(d,b),c=new B(b),c.parentLocale=uf[a],uf[a]=c, +// backwards compat for now: also set the locale +Za(a)}else +// pass null for config to unupdate, useful for tests +null!=uf[a]&&(null!=uf[a].parentLocale?uf[a]=uf[a].parentLocale:null!=uf[a]&&delete uf[a]);return uf[a]} +// returns locale data +function ab(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return qf;if(!c(a)){if(b=Ya(a))return b;a=[a]}return Xa(a)}function bb(){return oe(uf)}function cb(a){var b,c=a._a;return c&&-2===l(a).overflow&&(b=c[We]<0||c[We]>11?We:c[Xe]<1||c[Xe]>da(c[Ve],c[We])?Xe:c[Ye]<0||c[Ye]>24||24===c[Ye]&&(0!==c[Ze]||0!==c[$e]||0!==c[_e])?Ye:c[Ze]<0||c[Ze]>59?Ze:c[$e]<0||c[$e]>59?$e:c[_e]<0||c[_e]>999?_e:-1,l(a)._overflowDayOfYear&&(Ve>b||b>Xe)&&(b=Xe),l(a)._overflowWeeks&&-1===b&&(b=af),l(a)._overflowWeekday&&-1===b&&(b=bf),l(a).overflow=b),a} +// date from iso format +function db(a){var b,c,d,e,f,g,h=a._i,i=vf.exec(h)||wf.exec(h);if(i){for(l(a).iso=!0,b=0,c=yf.length;c>b;b++)if(yf[b][1].exec(i[1])){e=yf[b][0],d=yf[b][2]!==!1;break}if(null==e)return void(a._isValid=!1);if(i[3]){for(b=0,c=zf.length;c>b;b++)if(zf[b][1].exec(i[3])){ +// match[2] should be 'T' or space +f=(i[2]||" ")+zf[b][0];break}if(null==f)return void(a._isValid=!1)}if(!d&&null!=f)return void(a._isValid=!1);if(i[4]){if(!xf.exec(i[4]))return void(a._isValid=!1);g="Z"}a._f=e+(f||"")+(g||""),jb(a)}else a._isValid=!1} +// date from iso format or fallback +function eb(b){var c=Af.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(db(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))} +// Pick the first defined of two or three arguments. +function fb(a,b,c){return null!=a?a:null!=b?b:c}function gb(b){ +// hooks is actually the exported moment object +var c=new Date(a.now());return b._useUTC?[c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate()]:[c.getFullYear(),c.getMonth(),c.getDate()]} +// convert an array to a date. +// the array should mirror the parameters below +// note: all values past the year are optional and will default to the lowest possible value. +// [year, month, day , hour, minute, second, millisecond] +function hb(a){var b,c,d,e,f=[];if(!a._d){ +// Default to current date. +// * if no year, month, day of month are given, default to today +// * if day of month is given, default month and year +// * if month is given, default only year +// * if year is given, don't default anything +for(d=gb(a),a._w&&null==a._a[Xe]&&null==a._a[We]&&ib(a),a._dayOfYear&&(e=fb(a._a[Ve],d[Ve]),a._dayOfYear>oa(e)&&(l(a)._overflowDayOfYear=!0),c=sa(e,0,a._dayOfYear),a._a[We]=c.getUTCMonth(),a._a[Xe]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b]; +// Zero out whatever was not defaulted, including time +for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b]; +// Check for 24:00:00.000 +24===a._a[Ye]&&0===a._a[Ze]&&0===a._a[$e]&&0===a._a[_e]&&(a._nextDay=!0,a._a[Ye]=0),a._d=(a._useUTC?sa:ra).apply(null,f), +// Apply timezone offset from input. The actual utcOffset can be changed +// with parseZone. +null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[Ye]=24)}}function ib(a){var b,c,d,e,f,g,h,i;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=fb(b.GG,a._a[Ve],va(rb(),1,4).year),d=fb(b.W,1),e=fb(b.E,1),(1>e||e>7)&&(i=!0)):(f=a._locale._week.dow,g=a._locale._week.doy,c=fb(b.gg,a._a[Ve],va(rb(),f,g).year),d=fb(b.w,1),null!=b.d?(e=b.d,(0>e||e>6)&&(i=!0)):null!=b.e?(e=b.e+f,(b.e<0||b.e>6)&&(i=!0)):e=f),1>d||d>wa(c,f,g)?l(a)._overflowWeeks=!0:null!=i?l(a)._overflowWeekday=!0:(h=ua(c,d,e,f,g),a._a[Ve]=h.year,a._dayOfYear=h.dayOfYear)} +// date from string and format string +function jb(b){ +// TODO: Move this to another part of the creation flow to prevent circular deps +if(b._f===a.ISO_8601)return void db(b);b._a=[],l(b).empty=!0; +// This array is used to make a Date, either with `new Date` or `Date.UTC` +var c,d,e,f,g,h=""+b._i,i=h.length,j=0;for(e=X(b._f,b._locale).match(ye)||[],c=0;c<e.length;c++)f=e[c],d=(h.match(Z(f,b))||[])[0],d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&l(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),j+=d.length),Be[f]?(d?l(b).empty=!1:l(b).unusedTokens.push(f),ca(f,d,b)):b._strict&&!d&&l(b).unusedTokens.push(f); +// add remaining unparsed input length to the string +l(b).charsLeftOver=i-j,h.length>0&&l(b).unusedInput.push(h), +// clear _12h flag if hour is <= 12 +b._a[Ye]<=12&&l(b).bigHour===!0&&b._a[Ye]>0&&(l(b).bigHour=void 0),l(b).parsedDateParts=b._a.slice(0),l(b).meridiem=b._meridiem, +// handle meridiem +b._a[Ye]=kb(b._locale,b._a[Ye],b._meridiem),hb(b),cb(b)}function kb(a,b,c){var d; +// Fallback +return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b} +// date from string and array of format strings +function lb(a){var b,c,d,e,f;if(0===a._f.length)return l(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;e<a._f.length;e++)f=0,b=p({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._f=a._f[e],jb(b),m(b)&&(f+=l(b).charsLeftOver,f+=10*l(b).unusedTokens.length,l(b).score=f,(null==d||d>f)&&(d=f,c=b));i(a,c||b)}function mb(a){if(!a._d){var b=K(a._i);a._a=g([b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],function(a){return a&&parseInt(a,10)}),hb(a)}}function nb(a){var b=new q(cb(ob(a))); +// Adding is smart enough around DST +return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function ob(a){var b=a._i,d=a._f;return a._locale=a._locale||ab(a._l),null===b||void 0===d&&""===b?n({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),r(b)?new q(cb(b)):(c(d)?lb(a):f(b)?a._d=b:d?jb(a):pb(a),m(a)||(a._d=null),a))}function pb(b){var d=b._i;void 0===d?b._d=new Date(a.now()):f(d)?b._d=new Date(d.valueOf()):"string"==typeof d?eb(b):c(d)?(b._a=g(d.slice(0),function(a){return parseInt(a,10)}),hb(b)):"object"==typeof d?mb(b):"number"==typeof d? +// from milliseconds +b._d=new Date(d):a.createFromInputFallback(b)}function qb(a,b,f,g,h){var i={}; +// object construction must be done this way. +// https://github.com/moment/moment/issues/1423 +return"boolean"==typeof f&&(g=f,f=void 0),(d(a)&&e(a)||c(a)&&0===a.length)&&(a=void 0),i._isAMomentObject=!0,i._useUTC=i._isUTC=h,i._l=f,i._i=a,i._f=b,i._strict=g,nb(i)}function rb(a,b,c,d){return qb(a,b,c,d,!1)} +// Pick a moment m from moments so that m[fn](other) is true for all +// other. This relies on the function fn to be transitive. +// +// moments should either be an array of moment objects or an array, whose +// first element is an array of moment objects. +function sb(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return rb();for(d=b[0],e=1;e<b.length;++e)b[e].isValid()&&!b[e][a](d)||(d=b[e]);return d} +// TODO: Use [].sort instead? +function tb(){var a=[].slice.call(arguments,0);return sb("isBefore",a)}function ub(){var a=[].slice.call(arguments,0);return sb("isAfter",a)}function vb(a){var b=K(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0; +// representation for dateAddRemove +this._milliseconds=+k+1e3*j+// 1000 +6e4*i+// 1000 * 60 +1e3*h*60*60,//using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978 +// Because of dateAddRemove treats 24 hours as different from a +// day when working around DST, we need to store them separately +this._days=+g+7*f, +// It is impossible translate months into days without knowing +// which months you are are talking about, so we have to store +// it separately. +this._months=+e+3*d+12*c,this._data={},this._locale=ab(),this._bubble()}function wb(a){return a instanceof vb} +// FORMATTING +function xb(a,b){T(a,0,0,function(){var a=this.utcOffset(),c="+";return 0>a&&(a=-a,c="-"),c+S(~~(a/60),2)+b+S(~~a%60,2)})}function yb(a,b){var c=(b||"").match(a)||[],d=c[c.length-1]||[],e=(d+"").match(Ef)||["-",0,0],f=+(60*e[1])+t(e[2]);return"+"===e[0]?f:-f} +// Return a moment from input, that is local/utc/zone equivalent to model. +function zb(b,c){var d,e; +// Use low-level api, because this fn is low-level api. +return c._isUTC?(d=c.clone(),e=(r(b)||f(b)?b.valueOf():rb(b).valueOf())-d.valueOf(),d._d.setTime(d._d.valueOf()+e),a.updateOffset(d,!1),d):rb(b).local()}function Ab(a){ +// On Firefox.24 Date#getTimezoneOffset returns a floating point. +// https://github.com/moment/moment/pull/1871 +return 15*-Math.round(a._d.getTimezoneOffset()/15)} +// MOMENTS +// keepLocalTime = true means only change the timezone, without +// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> +// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset +// +0200, so we adjust the time as needed, to be valid. +// +// Keeping the time actually adds/subtracts (one hour) +// from the actual represented time. That is why we call updateOffset +// a second time. In case it wants us to change the offset again +// _changeInProgress == true case, then we have to adjust, because +// there is no such time in the given timezone. +function Bb(b,c){var d,e=this._offset||0;return this.isValid()?null!=b?("string"==typeof b?b=yb(Qe,b):Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ab(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?Sb(this,Mb(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ab(this):null!=b?this:NaN}function Cb(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Db(a){return this.utcOffset(0,a)}function Eb(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ab(this),"m")),this}function Fb(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(yb(Pe,this._i)),this}function Gb(a){return this.isValid()?(a=a?rb(a).utcOffset():0,(this.utcOffset()-a)%60===0):!1}function Hb(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ib(){if(!o(this._isDSTShifted))return this._isDSTShifted;var a={};if(p(a,this),a=ob(a),a._a){var b=a._isUTC?j(a._a):rb(a._a);this._isDSTShifted=this.isValid()&&u(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Jb(){return this.isValid()?!this._isUTC:!1}function Kb(){return this.isValid()?this._isUTC:!1}function Lb(){return this.isValid()?this._isUTC&&0===this._offset:!1}function Mb(a,b){var c,d,e,f=a, +// matching against regexp is expensive, do it on demand +g=null;// checks for null or undefined +return wb(a)?f={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(f={},b?f[b]=a:f.milliseconds=a):(g=Ff.exec(a))?(c="-"===g[1]?-1:1,f={y:0,d:t(g[Xe])*c,h:t(g[Ye])*c,m:t(g[Ze])*c,s:t(g[$e])*c,ms:t(g[_e])*c}):(g=Gf.exec(a))?(c="-"===g[1]?-1:1,f={y:Nb(g[2],c),M:Nb(g[3],c),w:Nb(g[4],c),d:Nb(g[5],c),h:Nb(g[6],c),m:Nb(g[7],c),s:Nb(g[8],c)}):null==f?f={}:"object"==typeof f&&("from"in f||"to"in f)&&(e=Pb(rb(f.from),rb(f.to)),f={},f.ms=e.milliseconds,f.M=e.months),d=new vb(f),wb(a)&&h(a,"_locale")&&(d._locale=a._locale),d}function Nb(a,b){ +// We'd normally use ~~inp for this, but unfortunately it also +// converts floats to ints. +// inp may be undefined, so careful calling replace on it. +var c=a&&parseFloat(a.replace(",",".")); +// apply sign while we're at it +return(isNaN(c)?0:c)*b}function Ob(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function Pb(a,b){var c;return a.isValid()&&b.isValid()?(b=zb(b,a),a.isBefore(b)?c=Ob(a,b):(c=Ob(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c):{milliseconds:0,months:0}}function Qb(a){return 0>a?-1*Math.round(-1*a):Math.round(a)} +// TODO: remove 'name' arg after deprecation is removed +function Rb(a,b){return function(c,d){var e,f; +//invert the arguments, but complain about it +return null===d||isNaN(+d)||(x(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Mb(c,d),Sb(this,e,a),this}}function Sb(b,c,d,e){var f=c._milliseconds,g=Qb(c._days),h=Qb(c._months);b.isValid()&&(e=null==e?!0:e,f&&b._d.setTime(b._d.valueOf()+f*d),g&&P(b,"Date",O(b,"Date")+g*d),h&&ia(b,O(b,"Month")+h*d),e&&a.updateOffset(b,g||h))}function Tb(a,b){var c=a.diff(b,"days",!0);return-6>c?"sameElse":-1>c?"lastWeek":0>c?"lastDay":1>c?"sameDay":2>c?"nextDay":7>c?"nextWeek":"sameElse"}function Ub(b,c){ +// We want to compare the start of today, vs this. +// Getting start-of-today depends on whether we're local/utc/offset or not. +var d=b||rb(),e=zb(d,this).startOf("day"),f=a.calendarFormat(this,e)||"sameElse",g=c&&(y(c[f])?c[f].call(this,d):c[f]);return this.format(g||this.localeData().calendar(f,this,rb(d)))}function Vb(){return new q(this)}function Wb(a,b){var c=r(a)?a:rb(a);return this.isValid()&&c.isValid()?(b=J(o(b)?"millisecond":b),"millisecond"===b?this.valueOf()>c.valueOf():c.valueOf()<this.clone().startOf(b).valueOf()):!1}function Xb(a,b){var c=r(a)?a:rb(a);return this.isValid()&&c.isValid()?(b=J(o(b)?"millisecond":b),"millisecond"===b?this.valueOf()<c.valueOf():this.clone().endOf(b).valueOf()<c.valueOf()):!1}function Yb(a,b,c,d){return d=d||"()",("("===d[0]?this.isAfter(a,c):!this.isBefore(a,c))&&(")"===d[1]?this.isBefore(b,c):!this.isAfter(b,c))}function Zb(a,b){var c,d=r(a)?a:rb(a);return this.isValid()&&d.isValid()?(b=J(b||"millisecond"),"millisecond"===b?this.valueOf()===d.valueOf():(c=d.valueOf(),this.clone().startOf(b).valueOf()<=c&&c<=this.clone().endOf(b).valueOf())):!1}function $b(a,b){return this.isSame(a,b)||this.isAfter(a,b)}function _b(a,b){return this.isSame(a,b)||this.isBefore(a,b)}function ac(a,b,c){var d,e,f,g;// 1000 +// 1000 * 60 +// 1000 * 60 * 60 +// 1000 * 60 * 60 * 24, negate dst +// 1000 * 60 * 60 * 24 * 7, negate dst +return this.isValid()?(d=zb(a,this),d.isValid()?(e=6e4*(d.utcOffset()-this.utcOffset()),b=J(b),"year"===b||"month"===b||"quarter"===b?(g=bc(this,d),"quarter"===b?g/=3:"year"===b&&(g/=12)):(f=this-d,g="second"===b?f/1e3:"minute"===b?f/6e4:"hour"===b?f/36e5:"day"===b?(f-e)/864e5:"week"===b?(f-e)/6048e5:f),c?g:s(g)):NaN):NaN}function bc(a,b){ +// difference in months +var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()), +// b is in (anchor - 1 month, anchor + 1 month) +f=a.clone().add(e,"months"); +//check for negative zero, return zero if negative zero +// linear across the month +// linear across the month +return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)||0}function cc(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function dc(){var a=this.clone().utc();return 0<a.year()&&a.year()<=9999?y(Date.prototype.toISOString)?this.toDate().toISOString():W(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):W(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function ec(b){b||(b=this.isUtc()?a.defaultFormatUtc:a.defaultFormat);var c=W(this,b);return this.localeData().postformat(c)}function fc(a,b){return this.isValid()&&(r(a)&&a.isValid()||rb(a).isValid())?Mb({to:this,from:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function gc(a){return this.from(rb(),a)}function hc(a,b){return this.isValid()&&(r(a)&&a.isValid()||rb(a).isValid())?Mb({from:this,to:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function ic(a){return this.to(rb(),a)} +// If passed a locale key, it will set the locale for this +// instance. Otherwise, it will return the locale configuration +// variables for this instance. +function jc(a){var b;return void 0===a?this._locale._abbr:(b=ab(a),null!=b&&(this._locale=b),this)}function kc(){return this._locale}function lc(a){ +// the following switch intentionally omits break keywords +// to utilize falling through the cases. +switch(a=J(a)){case"year":this.month(0);/* falls through */ +case"quarter":case"month":this.date(1);/* falls through */ +case"week":case"isoWeek":case"day":case"date":this.hours(0);/* falls through */ +case"hour":this.minutes(0);/* falls through */ +case"minute":this.seconds(0);/* falls through */ +case"second":this.milliseconds(0)} +// weeks are a special case +// quarters are also special +return"week"===a&&this.weekday(0),"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this}function mc(a){ +// 'date' is an alias for 'day', so it should be considered as such. +return a=J(a),void 0===a||"millisecond"===a?this:("date"===a&&(a="day"),this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms"))}function nc(){return this._d.valueOf()-6e4*(this._offset||0)}function oc(){return Math.floor(this.valueOf()/1e3)}function pc(){return new Date(this.valueOf())}function qc(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.minute(),a.second(),a.millisecond()]}function rc(){var a=this;return{years:a.year(),months:a.month(),date:a.date(),hours:a.hours(),minutes:a.minutes(),seconds:a.seconds(),milliseconds:a.milliseconds()}}function sc(){ +// new Date(NaN).toJSON() === null +return this.isValid()?this.toISOString():null}function tc(){return m(this)}function uc(){return i({},l(this))}function vc(){return l(this).overflow}function wc(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function xc(a,b){T(0,[a,a.length],0,b)} +// MOMENTS +function yc(a){return Cc.call(this,a,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function zc(a){return Cc.call(this,a,this.isoWeek(),this.isoWeekday(),1,4)}function Ac(){return wa(this.year(),1,4)}function Bc(){var a=this.localeData()._week;return wa(this.year(),a.dow,a.doy)}function Cc(a,b,c,d,e){var f;return null==a?va(this,d,e).year:(f=wa(a,d,e),b>f&&(b=f),Dc.call(this,a,b,c,d,e))}function Dc(a,b,c,d,e){var f=ua(a,b,c,d,e),g=sa(f.year,0,f.dayOfYear);return this.year(g.getUTCFullYear()),this.month(g.getUTCMonth()),this.date(g.getUTCDate()),this} +// MOMENTS +function Ec(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)} +// HELPERS +// MOMENTS +function Fc(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function Gc(a,b){b[_e]=t(1e3*("0."+a))} +// MOMENTS +function Hc(){return this._isUTC?"UTC":""}function Ic(){return this._isUTC?"Coordinated Universal Time":""}function Jc(a){return rb(1e3*a)}function Kc(){return rb.apply(null,arguments).parseZone()}function Lc(a){return a}function Mc(a,b,c,d){var e=ab(),f=j().set(d,b);return e[c](f,a)}function Nc(a,b,c){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return Mc(a,b,c,"month");var d,e=[];for(d=0;12>d;d++)e[d]=Mc(a,d,c,"month");return e} +// () +// (5) +// (fmt, 5) +// (fmt) +// (true) +// (true, 5) +// (true, fmt, 5) +// (true, fmt) +function Oc(a,b,c,d){"boolean"==typeof a?("number"==typeof b&&(c=b,b=void 0),b=b||""):(b=a,c=b,a=!1,"number"==typeof b&&(c=b,b=void 0),b=b||"");var e=ab(),f=a?e._week.dow:0;if(null!=c)return Mc(b,(c+f)%7,d,"day");var g,h=[];for(g=0;7>g;g++)h[g]=Mc(b,(g+f)%7,d,"day");return h}function Pc(a,b){return Nc(a,b,"months")}function Qc(a,b){return Nc(a,b,"monthsShort")}function Rc(a,b,c){return Oc(a,b,c,"weekdays")}function Sc(a,b,c){return Oc(a,b,c,"weekdaysShort")}function Tc(a,b,c){return Oc(a,b,c,"weekdaysMin")}function Uc(){var a=this._data;return this._milliseconds=Sf(this._milliseconds),this._days=Sf(this._days),this._months=Sf(this._months),a.milliseconds=Sf(a.milliseconds),a.seconds=Sf(a.seconds),a.minutes=Sf(a.minutes),a.hours=Sf(a.hours),a.months=Sf(a.months),a.years=Sf(a.years),this}function Vc(a,b,c,d){var e=Mb(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()} +// supports only 2.0-style add(1, 's') or add(duration) +function Wc(a,b){return Vc(this,a,b,1)} +// supports only 2.0-style subtract(1, 's') or subtract(duration) +function Xc(a,b){return Vc(this,a,b,-1)}function Yc(a){return 0>a?Math.floor(a):Math.ceil(a)}function Zc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data; +// if we have a mix of positive and negative values, bubble down first +// check: https://github.com/moment/moment/issues/2166 +// The following code bubbles up values, see the tests for +// examples of what that means. +// convert days to months +// 12 months -> 1 year +return f>=0&&g>=0&&h>=0||0>=f&&0>=g&&0>=h||(f+=864e5*Yc(_c(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=s(f/1e3),i.seconds=a%60,b=s(a/60),i.minutes=b%60,c=s(b/60),i.hours=c%24,g+=s(c/24),e=s($c(g)),h+=e,g-=Yc(_c(e)),d=s(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function $c(a){ +// 400 years have 146097 days (taking into account leap year rules) +// 400 years have 12 months === 4800 +return 4800*a/146097}function _c(a){ +// the reverse of daysToMonths +return 146097*a/4800}function ad(a){var b,c,d=this._milliseconds;if(a=J(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+$c(b),"month"===a?c:c/12;switch(b=this._days+Math.round(_c(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3; +// Math.floor prevents floating point math errors here +case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}} +// TODO: Use this.as('ms')? +function bd(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*t(this._months/12)}function cd(a){return function(){return this.as(a)}}function dd(a){return a=J(a),this[a+"s"]()}function ed(a){return function(){return this._data[a]}}function fd(){return s(this.days()/7)} +// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize +function gd(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function hd(a,b,c){var d=Mb(a).abs(),e=gg(d.as("s")),f=gg(d.as("m")),g=gg(d.as("h")),h=gg(d.as("d")),i=gg(d.as("M")),j=gg(d.as("y")),k=e<hg.s&&["s",e]||1>=f&&["m"]||f<hg.m&&["mm",f]||1>=g&&["h"]||g<hg.h&&["hh",g]||1>=h&&["d"]||h<hg.d&&["dd",h]||1>=i&&["M"]||i<hg.M&&["MM",i]||1>=j&&["y"]||["yy",j];return k[2]=b,k[3]=+a>0,k[4]=c,gd.apply(null,k)} +// This function allows you to set the rounding function for relative time strings +function id(a){return void 0===a?gg:"function"==typeof a?(gg=a,!0):!1} +// This function allows you to set a threshold for relative time strings +function jd(a,b){return void 0===hg[a]?!1:void 0===b?hg[a]:(hg[a]=b,!0)}function kd(a){var b=this.localeData(),c=hd(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function ld(){ +// for ISO strings we do not use the normal bubbling rules: +// * milliseconds bubble up until they become hours +// * days do not bubble at all +// * months bubble up until they become years +// This is because there is no context-free conversion between hours and days +// (think of clock changes) +// and also not between days and months (28-31 days per month) +var a,b,c,d=ig(this._milliseconds)/1e3,e=ig(this._days),f=ig(this._months);a=s(d/60),b=s(a/60),d%=60,a%=60,c=s(f/12),f%=12; +// inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js +var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(0>m?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}function md(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function nd(a,b,c){var d={mm:b?"хвіліна_хвіліны_хвілін":"хвіліну_хвіліны_хвілін",hh:b?"гадзіна_гадзіны_гадзін":"гадзіну_гадзіны_гадзін",dd:"дзень_дні_дзён",MM:"месяц_месяцы_месяцаў",yy:"год_гады_гадоў"};return"m"===c?b?"хвіліна":"хвіліну":"h"===c?b?"гадзіна":"гадзіну":a+" "+md(d[c],+a)}function od(a,b,c){var d={mm:"munutenn",MM:"miz",dd:"devezh"};return a+" "+rd(d[c],a)}function pd(a){switch(qd(a)){case 1:case 3:case 4:case 5:case 9:return a+" bloaz";default:return a+" vloaz"}}function qd(a){return a>9?qd(a%10):a}function rd(a,b){return 2===b?sd(a):a}function sd(a){var b={m:"v",b:"v",d:"z"};return void 0===b[a.charAt(0)]?a:b[a.charAt(0)]+a.substring(1)}function td(a,b,c){var d=a+" ";switch(c){case"m":return b?"jedna minuta":"jedne minute";case"mm":return d+=1===a?"minuta":2===a||3===a||4===a?"minute":"minuta";case"h":return b?"jedan sat":"jednog sata";case"hh":return d+=1===a?"sat":2===a||3===a||4===a?"sata":"sati";case"dd":return d+=1===a?"dan":"dana";case"MM":return d+=1===a?"mjesec":2===a||3===a||4===a?"mjeseca":"mjeseci";case"yy":return d+=1===a?"godina":2===a||3===a||4===a?"godine":"godina"}}function ud(a){return a>1&&5>a&&1!==~~(a/10)}function vd(a,b,c,d){var e=a+" ";switch(c){case"s":// a few seconds / in a few seconds / a few seconds ago +return b||d?"pár sekund":"pár sekundami";case"m":// a minute / in a minute / a minute ago +return b?"minuta":d?"minutu":"minutou";case"mm":// 9 minutes / in 9 minutes / 9 minutes ago +// 9 minutes / in 9 minutes / 9 minutes ago +return b||d?e+(ud(a)?"minuty":"minut"):e+"minutami";break;case"h":// an hour / in an hour / an hour ago +return b?"hodina":d?"hodinu":"hodinou";case"hh":// 9 hours / in 9 hours / 9 hours ago +// 9 hours / in 9 hours / 9 hours ago +return b||d?e+(ud(a)?"hodiny":"hodin"):e+"hodinami";break;case"d":// a day / in a day / a day ago +return b||d?"den":"dnem";case"dd":// 9 days / in 9 days / 9 days ago +// 9 days / in 9 days / 9 days ago +return b||d?e+(ud(a)?"dny":"dní"):e+"dny";break;case"M":// a month / in a month / a month ago +return b||d?"měsíc":"měsícem";case"MM":// 9 months / in 9 months / 9 months ago +// 9 months / in 9 months / 9 months ago +return b||d?e+(ud(a)?"měsíce":"měsíců"):e+"měsíci";break;case"y":// a year / in a year / a year ago +return b||d?"rok":"rokem";case"yy":// 9 years / in 9 years / 9 years ago +// 9 years / in 9 years / 9 years ago +return b||d?e+(ud(a)?"roky":"let"):e+"lety"}}function wd(a,b,c,d){var e={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[a+" Tage",a+" Tagen"],M:["ein Monat","einem Monat"],MM:[a+" Monate",a+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[a+" Jahre",a+" Jahren"]};return b?e[c][0]:e[c][1]}function xd(a,b,c,d){var e={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[a+" Tage",a+" Tagen"],M:["ein Monat","einem Monat"],MM:[a+" Monate",a+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[a+" Jahre",a+" Jahren"]};return b?e[c][0]:e[c][1]}function yd(a,b,c,d){var e={s:["mõne sekundi","mõni sekund","paar sekundit"],m:["ühe minuti","üks minut"],mm:[a+" minuti",a+" minutit"],h:["ühe tunni","tund aega","üks tund"],hh:[a+" tunni",a+" tundi"],d:["ühe päeva","üks päev"],M:["kuu aja","kuu aega","üks kuu"],MM:[a+" kuu",a+" kuud"],y:["ühe aasta","aasta","üks aasta"],yy:[a+" aasta",a+" aastat"]};return b?e[c][2]?e[c][2]:e[c][1]:d?e[c][0]:e[c][1]}function zd(a,b,c,d){var e="";switch(c){case"s":return d?"muutaman sekunnin":"muutama sekunti";case"m":return d?"minuutin":"minuutti";case"mm":e=d?"minuutin":"minuuttia";break;case"h":return d?"tunnin":"tunti";case"hh":e=d?"tunnin":"tuntia";break;case"d":return d?"päivän":"päivä";case"dd":e=d?"päivän":"päivää";break;case"M":return d?"kuukauden":"kuukausi";case"MM":e=d?"kuukauden":"kuukautta";break;case"y":return d?"vuoden":"vuosi";case"yy":e=d?"vuoden":"vuotta"}return e=Ad(a,d)+" "+e}function Ad(a,b){return 10>a?b?Jg[a]:Ig[a]:a}function Bd(a,b,c){var d=a+" ";switch(c){case"m":return b?"jedna minuta":"jedne minute";case"mm":return d+=1===a?"minuta":2===a||3===a||4===a?"minute":"minuta";case"h":return b?"jedan sat":"jednog sata";case"hh":return d+=1===a?"sat":2===a||3===a||4===a?"sata":"sati";case"dd":return d+=1===a?"dan":"dana";case"MM":return d+=1===a?"mjesec":2===a||3===a||4===a?"mjeseca":"mjeseci";case"yy":return d+=1===a?"godina":2===a||3===a||4===a?"godine":"godina"}}function Cd(a,b,c,d){var e=a;switch(c){case"s":return d||b?"néhány másodperc":"néhány másodperce";case"m":return"egy"+(d||b?" perc":" perce");case"mm":return e+(d||b?" perc":" perce");case"h":return"egy"+(d||b?" óra":" órája");case"hh":return e+(d||b?" óra":" órája");case"d":return"egy"+(d||b?" nap":" napja");case"dd":return e+(d||b?" nap":" napja");case"M":return"egy"+(d||b?" hónap":" hónapja");case"MM":return e+(d||b?" hónap":" hónapja");case"y":return"egy"+(d||b?" év":" éve");case"yy":return e+(d||b?" év":" éve")}return""}function Dd(a){return(a?"":"[múlt] ")+"["+Tg[this.day()]+"] LT[-kor]"}function Ed(a){return a%100===11?!0:a%10!==1}function Fd(a,b,c,d){var e=a+" ";switch(c){case"s":return b||d?"nokkrar sekúndur":"nokkrum sekúndum";case"m":return b?"mínúta":"mínútu";case"mm":return Ed(a)?e+(b||d?"mínútur":"mínútum"):b?e+"mínúta":e+"mínútu";case"hh":return Ed(a)?e+(b||d?"klukkustundir":"klukkustundum"):e+"klukkustund";case"d":return b?"dagur":d?"dag":"degi";case"dd":return Ed(a)?b?e+"dagar":e+(d?"daga":"dögum"):b?e+"dagur":e+(d?"dag":"degi");case"M":return b?"mánuður":d?"mánuð":"mánuði";case"MM":return Ed(a)?b?e+"mánuðir":e+(d?"mánuði":"mánuðum"):b?e+"mánuður":e+(d?"mánuð":"mánuði");case"y":return b||d?"ár":"ári";case"yy":return Ed(a)?e+(b||d?"ár":"árum"):e+(b||d?"ár":"ári")}}function Gd(a,b,c,d){var e={m:["eng Minutt","enger Minutt"],h:["eng Stonn","enger Stonn"],d:["een Dag","engem Dag"],M:["ee Mount","engem Mount"],y:["ee Joer","engem Joer"]};return b?e[c][0]:e[c][1]}function Hd(a){var b=a.substr(0,a.indexOf(" "));return Jd(b)?"a "+a:"an "+a}function Id(a){var b=a.substr(0,a.indexOf(" "));return Jd(b)?"viru "+a:"virun "+a}/** + * Returns true if the word before the given number loses the '-n' ending. + * e.g. 'an 10 Deeg' but 'a 5 Deeg' + * + * @param number {integer} + * @returns {boolean} + */ +function Jd(a){if(a=parseInt(a,10),isNaN(a))return!1;if(0>a) +// Negative Number --> always true +return!0;if(10>a) +// Only 1 digit +return a>=4&&7>=a;if(100>a){ +// 2 digits +var b=a%10,c=a/10;return Jd(0===b?c:b)}if(1e4>a){ +// 3 or 4 digits --> recursively check first digit +for(;a>=10;)a/=10;return Jd(a)} +// Anything larger than 4 digits: recursively check first n-3 digits +return a/=1e3,Jd(a)}function Kd(a,b,c,d){return b?"kelios sekundės":d?"kelių sekundžių":"kelias sekundes"}function Ld(a,b,c,d){return b?Nd(c)[0]:d?Nd(c)[1]:Nd(c)[2]}function Md(a){return a%10===0||a>10&&20>a}function Nd(a){return Wg[a].split("_")}function Od(a,b,c,d){var e=a+" ";return 1===a?e+Ld(a,b,c[0],d):b?e+(Md(a)?Nd(c)[1]:Nd(c)[0]):d?e+Nd(c)[1]:e+(Md(a)?Nd(c)[1]:Nd(c)[2])}/** + * @param withoutSuffix boolean true = a length of time; false = before/after a period of time. + */ +function Pd(a,b,c){return c?b%10===1&&b%100!==11?a[2]:a[3]:b%10===1&&b%100!==11?a[0]:a[1]}function Qd(a,b,c){return a+" "+Pd(Xg[c],a,b)}function Rd(a,b,c){return Pd(Xg[c],a,b)}function Sd(a,b){return b?"dažas sekundes":"dažām sekundēm"}function Td(a,b,c,d){var e="";if(b)switch(c){case"s":e="काही सेकंद";break;case"m":e="एक मिनिट";break;case"mm":e="%d मिनिटे";break;case"h":e="एक तास";break;case"hh":e="%d तास";break;case"d":e="एक दिवस";break;case"dd":e="%d दिवस";break;case"M":e="एक महिना";break;case"MM":e="%d महिने";break;case"y":e="एक वर्ष";break;case"yy":e="%d वर्षे"}else switch(c){case"s":e="काही सेकंदां";break;case"m":e="एका मिनिटा";break;case"mm":e="%d मिनिटां";break;case"h":e="एका तासा";break;case"hh":e="%d तासां";break;case"d":e="एका दिवसा";break;case"dd":e="%d दिवसां";break;case"M":e="एका महिन्या";break;case"MM":e="%d महिन्यां";break;case"y":e="एका वर्षा";break;case"yy":e="%d वर्षां"}return e.replace(/%d/i,a)}function Ud(a){return 5>a%10&&a%10>1&&~~(a/10)%10!==1}function Vd(a,b,c){var d=a+" ";switch(c){case"m":return b?"minuta":"minutę";case"mm":return d+(Ud(a)?"minuty":"minut");case"h":return b?"godzina":"godzinę";case"hh":return d+(Ud(a)?"godziny":"godzin");case"MM":return d+(Ud(a)?"miesiące":"miesięcy");case"yy":return d+(Ud(a)?"lata":"lat")}}function Wd(a,b,c){var d={mm:"minute",hh:"ore",dd:"zile",MM:"luni",yy:"ani"},e=" ";return(a%100>=20||a>=100&&a%100===0)&&(e=" de "),a+e+d[c]}function Xd(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function Yd(a,b,c){var d={mm:b?"минута_минуты_минут":"минуту_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",MM:"месяц_месяца_месяцев",yy:"год_года_лет"};return"m"===c?b?"минута":"минуту":a+" "+Xd(d[c],+a)}function Zd(a){return a>1&&5>a}function $d(a,b,c,d){var e=a+" ";switch(c){case"s":// a few seconds / in a few seconds / a few seconds ago +return b||d?"pár sekúnd":"pár sekundami";case"m":// a minute / in a minute / a minute ago +return b?"minúta":d?"minútu":"minútou";case"mm":// 9 minutes / in 9 minutes / 9 minutes ago +// 9 minutes / in 9 minutes / 9 minutes ago +return b||d?e+(Zd(a)?"minúty":"minút"):e+"minútami";break;case"h":// an hour / in an hour / an hour ago +return b?"hodina":d?"hodinu":"hodinou";case"hh":// 9 hours / in 9 hours / 9 hours ago +// 9 hours / in 9 hours / 9 hours ago +return b||d?e+(Zd(a)?"hodiny":"hodín"):e+"hodinami";break;case"d":// a day / in a day / a day ago +return b||d?"deň":"dňom";case"dd":// 9 days / in 9 days / 9 days ago +// 9 days / in 9 days / 9 days ago +return b||d?e+(Zd(a)?"dni":"dní"):e+"dňami";break;case"M":// a month / in a month / a month ago +return b||d?"mesiac":"mesiacom";case"MM":// 9 months / in 9 months / 9 months ago +// 9 months / in 9 months / 9 months ago +return b||d?e+(Zd(a)?"mesiace":"mesiacov"):e+"mesiacmi";break;case"y":// a year / in a year / a year ago +return b||d?"rok":"rokom";case"yy":// 9 years / in 9 years / 9 years ago +// 9 years / in 9 years / 9 years ago +return b||d?e+(Zd(a)?"roky":"rokov"):e+"rokmi"}}function _d(a,b,c,d){var e=a+" ";switch(c){case"s":return b||d?"nekaj sekund":"nekaj sekundami";case"m":return b?"ena minuta":"eno minuto";case"mm":return e+=1===a?b?"minuta":"minuto":2===a?b||d?"minuti":"minutama":5>a?b||d?"minute":"minutami":b||d?"minut":"minutami";case"h":return b?"ena ura":"eno uro";case"hh":return e+=1===a?b?"ura":"uro":2===a?b||d?"uri":"urama":5>a?b||d?"ure":"urami":b||d?"ur":"urami";case"d":return b||d?"en dan":"enim dnem";case"dd":return e+=1===a?b||d?"dan":"dnem":2===a?b||d?"dni":"dnevoma":b||d?"dni":"dnevi";case"M":return b||d?"en mesec":"enim mesecem";case"MM":return e+=1===a?b||d?"mesec":"mesecem":2===a?b||d?"meseca":"mesecema":5>a?b||d?"mesece":"meseci":b||d?"mesecev":"meseci";case"y":return b||d?"eno leto":"enim letom";case"yy":return e+=1===a?b||d?"leto":"letom":2===a?b||d?"leti":"letoma":5>a?b||d?"leta":"leti":b||d?"let":"leti"}}function ae(a){var b=a;return b=-1!==a.indexOf("jaj")?b.slice(0,-3)+"leS":-1!==a.indexOf("jar")?b.slice(0,-3)+"waQ":-1!==a.indexOf("DIS")?b.slice(0,-3)+"nem":b+" pIq"}function be(a){var b=a;return b=-1!==a.indexOf("jaj")?b.slice(0,-3)+"Hu’":-1!==a.indexOf("jar")?b.slice(0,-3)+"wen":-1!==a.indexOf("DIS")?b.slice(0,-3)+"ben":b+" ret"}function ce(a,b,c,d){var e=de(a);switch(c){case"mm":return e+" tup";case"hh":return e+" rep";case"dd":return e+" jaj";case"MM":return e+" jar";case"yy":return e+" DIS"}}function de(a){var b=Math.floor(a%1e3/100),c=Math.floor(a%100/10),d=a%10,e="";return b>0&&(e+=qh[b]+"vatlh"),c>0&&(e+=(""!==e?" ":"")+qh[c]+"maH"),d>0&&(e+=(""!==e?" ":"")+qh[d]),""===e?"pagh":e}function ee(a,b,c,d){var e={s:["viensas secunds","'iensas secunds"],m:["'n míut","'iens míut"],mm:[a+" míuts",""+a+" míuts"],h:["'n þora","'iensa þora"],hh:[a+" þoras",""+a+" þoras"],d:["'n ziua","'iensa ziua"],dd:[a+" ziuas",""+a+" ziuas"],M:["'n mes","'iens mes"],MM:[a+" mesen",""+a+" mesen"],y:["'n ar","'iens ar"],yy:[a+" ars",""+a+" ars"]};return d?e[c][0]:b?e[c][0]:e[c][1]}function fe(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function ge(a,b,c){var d={mm:b?"хвилина_хвилини_хвилин":"хвилину_хвилини_хвилин",hh:b?"година_години_годин":"годину_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"};return"m"===c?b?"хвилина":"хвилину":"h"===c?b?"година":"годину":a+" "+fe(d[c],+a)}function he(a,b){var c={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".split("_"),accusative:"неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу".split("_"),genitive:"неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи".split("_")},d=/(\[[ВвУу]\]) ?dddd/.test(b)?"accusative":/\[?(?:минулої|наступної)? ?\] ?dddd/.test(b)?"genitive":"nominative";return c[d][a.day()]}function ie(a){return function(){return a+"о"+(11===this.hours()?"б":"")+"] LT"}}var je,ke;ke=Array.prototype.some?Array.prototype.some:function(a){for(var b=Object(this),c=b.length>>>0,d=0;c>d;d++)if(d in b&&a.call(this,b[d],d,b))return!0;return!1}; +// Plugins that add properties should also add the key here (null value), +// so we can properly clone ourselves. +var le=a.momentProperties=[],me=!1,ne={};a.suppressDeprecationWarnings=!1,a.deprecationHandler=null;var oe;oe=Object.keys?Object.keys:function(a){var b,c=[];for(b in a)h(a,b)&&c.push(b);return c};var pe,qe={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},re={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},se="Invalid date",te="%d",ue=/\d{1,2}/,ve={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},we={},xe={},ye=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,ze=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Ae={},Be={},Ce=/\d/,De=/\d\d/,Ee=/\d{3}/,Fe=/\d{4}/,Ge=/[+-]?\d{6}/,He=/\d\d?/,Ie=/\d\d\d\d?/,Je=/\d\d\d\d\d\d?/,Ke=/\d{1,3}/,Le=/\d{1,4}/,Me=/[+-]?\d{1,6}/,Ne=/\d+/,Oe=/[+-]?\d+/,Pe=/Z|[+-]\d\d:?\d\d/gi,Qe=/Z|[+-]\d\d(?::?\d\d)?/gi,Re=/[+-]?\d+(\.\d{1,3})?/,Se=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Te={},Ue={},Ve=0,We=1,Xe=2,Ye=3,Ze=4,$e=5,_e=6,af=7,bf=8;pe=Array.prototype.indexOf?Array.prototype.indexOf:function(a){ +// I know +var b;for(b=0;b<this.length;++b)if(this[b]===a)return b;return-1},T("M",["MM",2],"Mo",function(){return this.month()+1}),T("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),T("MMMM",0,0,function(a){return this.localeData().months(this,a)}),I("month","M"),L("month",8),Y("M",He),Y("MM",He,De),Y("MMM",function(a,b){return b.monthsShortRegex(a)}),Y("MMMM",function(a,b){return b.monthsRegex(a)}),aa(["M","MM"],function(a,b){b[We]=t(a)-1}),aa(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[We]=e:l(c).invalidMonth=a}); +// LOCALES +var cf=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/,df="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ef="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),ff=Se,gf=Se; +// FORMATTING +T("Y",0,0,function(){var a=this.year();return 9999>=a?""+a:"+"+a}),T(0,["YY",2],0,function(){return this.year()%100}),T(0,["YYYY",4],0,"year"),T(0,["YYYYY",5],0,"year"),T(0,["YYYYYY",6,!0],0,"year"), +// ALIASES +I("year","y"), +// PRIORITIES +L("year",1), +// PARSING +Y("Y",Oe),Y("YY",He,De),Y("YYYY",Le,Fe),Y("YYYYY",Me,Ge),Y("YYYYYY",Me,Ge),aa(["YYYYY","YYYYYY"],Ve),aa("YYYY",function(b,c){c[Ve]=2===b.length?a.parseTwoDigitYear(b):t(b)}),aa("YY",function(b,c){c[Ve]=a.parseTwoDigitYear(b)}),aa("Y",function(a,b){b[Ve]=parseInt(a,10)}), +// HOOKS +a.parseTwoDigitYear=function(a){return t(a)+(t(a)>68?1900:2e3)}; +// MOMENTS +var hf=N("FullYear",!0); +// FORMATTING +T("w",["ww",2],"wo","week"),T("W",["WW",2],"Wo","isoWeek"), +// ALIASES +I("week","w"),I("isoWeek","W"), +// PRIORITIES +L("week",5),L("isoWeek",5), +// PARSING +Y("w",He),Y("ww",He,De),Y("W",He),Y("WW",He,De),ba(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=t(a)});var jf={dow:0,// Sunday is the first day of the week. +doy:6}; +// FORMATTING +T("d",0,"do","day"),T("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),T("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),T("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),T("e",0,0,"weekday"),T("E",0,0,"isoWeekday"), +// ALIASES +I("day","d"),I("weekday","e"),I("isoWeekday","E"), +// PRIORITY +L("day",11),L("weekday",11),L("isoWeekday",11), +// PARSING +Y("d",He),Y("e",He),Y("E",He),Y("dd",function(a,b){return b.weekdaysMinRegex(a)}),Y("ddd",function(a,b){return b.weekdaysShortRegex(a)}),Y("dddd",function(a,b){return b.weekdaysRegex(a)}),ba(["dd","ddd","dddd"],function(a,b,c,d){var e=c._locale.weekdaysParse(a,d,c._strict); +// if we didn't get a weekday name, mark the date as invalid +null!=e?b.d=e:l(c).invalidWeekday=a}),ba(["d","e","E"],function(a,b,c,d){b[d]=t(a)}); +// LOCALES +var kf="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),lf="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),mf="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),nf=Se,of=Se,pf=Se;T("H",["HH",2],0,"hour"),T("h",["hh",2],0,Qa),T("k",["kk",2],0,Ra),T("hmm",0,0,function(){return""+Qa.apply(this)+S(this.minutes(),2)}),T("hmmss",0,0,function(){return""+Qa.apply(this)+S(this.minutes(),2)+S(this.seconds(),2)}),T("Hmm",0,0,function(){return""+this.hours()+S(this.minutes(),2)}),T("Hmmss",0,0,function(){return""+this.hours()+S(this.minutes(),2)+S(this.seconds(),2)}),Sa("a",!0),Sa("A",!1), +// ALIASES +I("hour","h"), +// PRIORITY +L("hour",13),Y("a",Ta),Y("A",Ta),Y("H",He),Y("h",He),Y("HH",He,De),Y("hh",He,De),Y("hmm",Ie),Y("hmmss",Je),Y("Hmm",Ie),Y("Hmmss",Je),aa(["H","HH"],Ye),aa(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),aa(["h","hh"],function(a,b,c){b[Ye]=t(a),l(c).bigHour=!0}),aa("hmm",function(a,b,c){var d=a.length-2;b[Ye]=t(a.substr(0,d)),b[Ze]=t(a.substr(d)),l(c).bigHour=!0}),aa("hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[Ye]=t(a.substr(0,d)),b[Ze]=t(a.substr(d,2)),b[$e]=t(a.substr(e)),l(c).bigHour=!0}),aa("Hmm",function(a,b,c){var d=a.length-2;b[Ye]=t(a.substr(0,d)),b[Ze]=t(a.substr(d))}),aa("Hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[Ye]=t(a.substr(0,d)),b[Ze]=t(a.substr(d,2)),b[$e]=t(a.substr(e))});var qf,rf=/[ap]\.?m?\.?/i,sf=N("Hours",!0),tf={calendar:qe,longDateFormat:re,invalidDate:se,ordinal:te,ordinalParse:ue,relativeTime:ve,months:df,monthsShort:ef,week:jf,weekdays:kf,weekdaysMin:mf,weekdaysShort:lf,meridiemParse:rf},uf={},vf=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,wf=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,xf=/Z|[+-]\d\d(?::?\d\d)?/,yf=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/], +// YYYYMM is NOT allowed by the standard +["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],zf=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Af=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=w("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}), +// constant that refers to the ISO standard +a.ISO_8601=function(){};var Bf=w("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var a=rb.apply(null,arguments);return this.isValid()&&a.isValid()?this>a?this:a:n()}),Cf=w("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var a=rb.apply(null,arguments);return this.isValid()&&a.isValid()?a>this?this:a:n()}),Df=function(){return Date.now?Date.now():+new Date};xb("Z",":"),xb("ZZ",""), +// PARSING +Y("Z",Qe),Y("ZZ",Qe),aa(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=yb(Qe,a)}); +// HELPERS +// timezone chunker +// '+10:00' > ['10', '00'] +// '-1530' > ['-15', '30'] +var Ef=/([\+\-]|\d\d)/gi; +// HOOKS +// This function will be called whenever a moment is mutated. +// It is intended to keep the offset in sync with the timezone. +a.updateOffset=function(){}; +// ASP.NET json date format regex +var Ff=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/,Gf=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;Mb.fn=vb.prototype;var Hf=Rb(1,"add"),If=Rb(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",a.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Jf=w("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)}); +// FORMATTING +T(0,["gg",2],0,function(){return this.weekYear()%100}),T(0,["GG",2],0,function(){return this.isoWeekYear()%100}),xc("gggg","weekYear"),xc("ggggg","weekYear"),xc("GGGG","isoWeekYear"),xc("GGGGG","isoWeekYear"), +// ALIASES +I("weekYear","gg"),I("isoWeekYear","GG"), +// PRIORITY +L("weekYear",1),L("isoWeekYear",1), +// PARSING +Y("G",Oe),Y("g",Oe),Y("GG",He,De),Y("gg",He,De),Y("GGGG",Le,Fe),Y("gggg",Le,Fe),Y("GGGGG",Me,Ge),Y("ggggg",Me,Ge),ba(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=t(a)}),ba(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}), +// FORMATTING +T("Q",0,"Qo","quarter"), +// ALIASES +I("quarter","Q"), +// PRIORITY +L("quarter",7), +// PARSING +Y("Q",Ce),aa("Q",function(a,b){b[We]=3*(t(a)-1)}), +// FORMATTING +T("D",["DD",2],"Do","date"), +// ALIASES +I("date","D"), +// PRIOROITY +L("date",9), +// PARSING +Y("D",He),Y("DD",He,De),Y("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),aa(["D","DD"],Xe),aa("Do",function(a,b){b[Xe]=t(a.match(He)[0],10)}); +// MOMENTS +var Kf=N("Date",!0); +// FORMATTING +T("DDD",["DDDD",3],"DDDo","dayOfYear"), +// ALIASES +I("dayOfYear","DDD"), +// PRIORITY +L("dayOfYear",4), +// PARSING +Y("DDD",Ke),Y("DDDD",Ee),aa(["DDD","DDDD"],function(a,b,c){c._dayOfYear=t(a)}), +// FORMATTING +T("m",["mm",2],0,"minute"), +// ALIASES +I("minute","m"), +// PRIORITY +L("minute",14), +// PARSING +Y("m",He),Y("mm",He,De),aa(["m","mm"],Ze); +// MOMENTS +var Lf=N("Minutes",!1); +// FORMATTING +T("s",["ss",2],0,"second"), +// ALIASES +I("second","s"), +// PRIORITY +L("second",15), +// PARSING +Y("s",He),Y("ss",He,De),aa(["s","ss"],$e); +// MOMENTS +var Mf=N("Seconds",!1); +// FORMATTING +T("S",0,0,function(){return~~(this.millisecond()/100)}),T(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),T(0,["SSS",3],0,"millisecond"),T(0,["SSSS",4],0,function(){return 10*this.millisecond()}),T(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),T(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),T(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),T(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),T(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}), +// ALIASES +I("millisecond","ms"), +// PRIORITY +L("millisecond",16), +// PARSING +Y("S",Ke,Ce),Y("SS",Ke,De),Y("SSS",Ke,Ee);var Nf;for(Nf="SSSS";Nf.length<=9;Nf+="S")Y(Nf,Ne);for(Nf="S";Nf.length<=9;Nf+="S")aa(Nf,Gc); +// MOMENTS +var Of=N("Milliseconds",!1); +// FORMATTING +T("z",0,0,"zoneAbbr"),T("zz",0,0,"zoneName");var Pf=q.prototype;Pf.add=Hf,Pf.calendar=Ub,Pf.clone=Vb,Pf.diff=ac,Pf.endOf=mc,Pf.format=ec,Pf.from=fc,Pf.fromNow=gc,Pf.to=hc,Pf.toNow=ic,Pf.get=Q,Pf.invalidAt=vc,Pf.isAfter=Wb,Pf.isBefore=Xb,Pf.isBetween=Yb,Pf.isSame=Zb,Pf.isSameOrAfter=$b,Pf.isSameOrBefore=_b,Pf.isValid=tc,Pf.lang=Jf,Pf.locale=jc,Pf.localeData=kc,Pf.max=Cf,Pf.min=Bf,Pf.parsingFlags=uc,Pf.set=R,Pf.startOf=lc,Pf.subtract=If,Pf.toArray=qc,Pf.toObject=rc,Pf.toDate=pc,Pf.toISOString=dc,Pf.toJSON=sc,Pf.toString=cc,Pf.unix=oc,Pf.valueOf=nc,Pf.creationData=wc, +// Year +Pf.year=hf,Pf.isLeapYear=qa, +// Week Year +Pf.weekYear=yc,Pf.isoWeekYear=zc, +// Quarter +Pf.quarter=Pf.quarters=Ec, +// Month +Pf.month=ja,Pf.daysInMonth=ka, +// Week +Pf.week=Pf.weeks=Aa,Pf.isoWeek=Pf.isoWeeks=Ba,Pf.weeksInYear=Bc,Pf.isoWeeksInYear=Ac, +// Day +Pf.date=Kf,Pf.day=Pf.days=Ja,Pf.weekday=Ka,Pf.isoWeekday=La,Pf.dayOfYear=Fc, +// Hour +Pf.hour=Pf.hours=sf, +// Minute +Pf.minute=Pf.minutes=Lf, +// Second +Pf.second=Pf.seconds=Mf, +// Millisecond +Pf.millisecond=Pf.milliseconds=Of, +// Offset +Pf.utcOffset=Bb,Pf.utc=Db,Pf.local=Eb,Pf.parseZone=Fb,Pf.hasAlignedHourOffset=Gb,Pf.isDST=Hb,Pf.isLocal=Jb,Pf.isUtcOffset=Kb,Pf.isUtc=Lb,Pf.isUTC=Lb, +// Timezone +Pf.zoneAbbr=Hc,Pf.zoneName=Ic, +// Deprecations +Pf.dates=w("dates accessor is deprecated. Use date instead.",Kf),Pf.months=w("months accessor is deprecated. Use month instead",ja),Pf.years=w("years accessor is deprecated. Use year instead",hf),Pf.zone=w("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",Cb),Pf.isDSTShifted=w("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",Ib);var Qf=Pf,Rf=B.prototype;Rf.calendar=C,Rf.longDateFormat=D,Rf.invalidDate=E,Rf.ordinal=F,Rf.preparse=Lc,Rf.postformat=Lc,Rf.relativeTime=G,Rf.pastFuture=H,Rf.set=z, +// Month +Rf.months=ea,Rf.monthsShort=fa,Rf.monthsParse=ha,Rf.monthsRegex=ma,Rf.monthsShortRegex=la, +// Week +Rf.week=xa,Rf.firstDayOfYear=za,Rf.firstDayOfWeek=ya, +// Day of Week +Rf.weekdays=Ea,Rf.weekdaysMin=Ga,Rf.weekdaysShort=Fa,Rf.weekdaysParse=Ia,Rf.weekdaysRegex=Ma,Rf.weekdaysShortRegex=Na,Rf.weekdaysMinRegex=Oa, +// Hours +Rf.isPM=Ua,Rf.meridiem=Va,Za("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===t(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}), +// Side effect imports +a.lang=w("moment.lang is deprecated. Use moment.locale instead.",Za),a.langData=w("moment.langData is deprecated. Use moment.localeData instead.",ab);var Sf=Math.abs,Tf=cd("ms"),Uf=cd("s"),Vf=cd("m"),Wf=cd("h"),Xf=cd("d"),Yf=cd("w"),Zf=cd("M"),$f=cd("y"),_f=ed("milliseconds"),ag=ed("seconds"),bg=ed("minutes"),cg=ed("hours"),dg=ed("days"),eg=ed("months"),fg=ed("years"),gg=Math.round,hg={s:45,// seconds to minute +m:45,// minutes to hour +h:22,// hours to day +d:26,// days to month +M:11},ig=Math.abs,jg=vb.prototype;jg.abs=Uc,jg.add=Wc,jg.subtract=Xc,jg.as=ad,jg.asMilliseconds=Tf,jg.asSeconds=Uf,jg.asMinutes=Vf,jg.asHours=Wf,jg.asDays=Xf,jg.asWeeks=Yf,jg.asMonths=Zf,jg.asYears=$f,jg.valueOf=bd,jg._bubble=Zc,jg.get=dd,jg.milliseconds=_f,jg.seconds=ag,jg.minutes=bg,jg.hours=cg,jg.days=dg,jg.weeks=fd,jg.months=eg,jg.years=fg,jg.humanize=kd,jg.toISOString=ld,jg.toString=ld,jg.toJSON=ld,jg.locale=jc,jg.localeData=kc, +// Deprecations +jg.toIsoString=w("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",ld),jg.lang=Jf, +// Side effect imports +// FORMATTING +T("X",0,0,"unix"),T("x",0,0,"valueOf"), +// PARSING +Y("x",Oe),Y("X",Re),aa("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),aa("x",function(a,b,c){c._d=new Date(t(a))}),a.version="2.14.1",b(rb),a.fn=Qf,a.min=tb,a.max=ub,a.now=Df,a.utc=j,a.unix=Jc,a.months=Pc,a.isDate=f,a.locale=Za,a.invalid=n,a.duration=Mb,a.isMoment=r,a.weekdays=Rc,a.parseZone=Kc,a.localeData=ab,a.isDuration=wb,a.monthsShort=Qc,a.weekdaysMin=Tc,a.defineLocale=$a,a.updateLocale=_a,a.locales=bb,a.weekdaysShort=Sc,a.normalizeUnits=J,a.relativeTimeRounding=id,a.relativeTimeThreshold=jd,a.calendarFormat=Tb,a.prototype=Qf;var kg=a,lg=(kg.defineLocale("af",{months:"Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des".split("_"),weekdays:"Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag".split("_"),weekdaysShort:"Son_Maa_Din_Woe_Don_Vry_Sat".split("_"),weekdaysMin:"So_Ma_Di_Wo_Do_Vr_Sa".split("_"),meridiemParse:/vm|nm/i,isPM:function(a){return/^nm$/i.test(a)},meridiem:function(a,b,c){return 12>a?c?"vm":"VM":c?"nm":"NM"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Vandag om] LT",nextDay:"[Môre om] LT",nextWeek:"dddd [om] LT",lastDay:"[Gister om] LT",lastWeek:"[Laas] dddd [om] LT",sameElse:"L"},relativeTime:{future:"oor %s",past:"%s gelede",s:"'n paar sekondes",m:"'n minuut",mm:"%d minute",h:"'n uur",hh:"%d ure",d:"'n dag",dd:"%d dae",M:"'n maand",MM:"%d maande",y:"'n jaar",yy:"%d jaar"},ordinalParse:/\d{1,2}(ste|de)/,ordinal:function(a){return a+(1===a||8===a||a>=20?"ste":"de")},week:{dow:1,// Maandag is die eerste dag van die week. +doy:4}}),kg.defineLocale("ar-ma",{months:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),weekdays:"الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:6,// Saturday is the first day of the week. +doy:12}}),{1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"}),mg={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"},ng=(kg.defineLocale("ar-sa",{months:"يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(a){return"م"===a},meridiem:function(a,b,c){return 12>a?"ص":"م"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},preparse:function(a){return a.replace(/[١٢٣٤٥٦٧٨٩٠]/g,function(a){return mg[a]}).replace(/،/g,",")},postformat:function(a){return a.replace(/\d/g,function(a){return lg[a]}).replace(/,/g,"،")},week:{dow:6,// Saturday is the first day of the week. +doy:12}}),kg.defineLocale("ar-tn",{months:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:1,// Monday is the first day of the week. +doy:4}}),{1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"}),og={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"},pg=function(a){return 0===a?0:1===a?1:2===a?2:a%100>=3&&10>=a%100?3:a%100>=11?4:5},qg={s:["أقل من ثانية","ثانية واحدة",["ثانيتان","ثانيتين"],"%d ثوان","%d ثانية","%d ثانية"],m:["أقل من دقيقة","دقيقة واحدة",["دقيقتان","دقيقتين"],"%d دقائق","%d دقيقة","%d دقيقة"],h:["أقل من ساعة","ساعة واحدة",["ساعتان","ساعتين"],"%d ساعات","%d ساعة","%d ساعة"],d:["أقل من يوم","يوم واحد",["يومان","يومين"],"%d أيام","%d يومًا","%d يوم"],M:["أقل من شهر","شهر واحد",["شهران","شهرين"],"%d أشهر","%d شهرا","%d شهر"],y:["أقل من عام","عام واحد",["عامان","عامين"],"%d أعوام","%d عامًا","%d عام"]},rg=function(a){return function(b,c,d,e){var f=pg(b),g=qg[a][pg(b)];return 2===f&&(g=g[c?0:1]),g.replace(/%d/i,b)}},sg=["كانون الثاني يناير","شباط فبراير","آذار مارس","نيسان أبريل","أيار مايو","حزيران يونيو","تموز يوليو","آب أغسطس","أيلول سبتمبر","تشرين الأول أكتوبر","تشرين الثاني نوفمبر","كانون الأول ديسمبر"],tg=(kg.defineLocale("ar",{months:sg,monthsShort:sg,weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/M/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(a){return"م"===a},meridiem:function(a,b,c){return 12>a?"ص":"م"},calendar:{sameDay:"[اليوم عند الساعة] LT",nextDay:"[غدًا عند الساعة] LT",nextWeek:"dddd [عند الساعة] LT",lastDay:"[أمس عند الساعة] LT",lastWeek:"dddd [عند الساعة] LT",sameElse:"L"},relativeTime:{future:"بعد %s",past:"منذ %s",s:rg("s"),m:rg("m"),mm:rg("m"),h:rg("h"),hh:rg("h"),d:rg("d"),dd:rg("d"),M:rg("M"),MM:rg("M"),y:rg("y"),yy:rg("y")},preparse:function(a){return a.replace(/\u200f/g,"").replace(/[١٢٣٤٥٦٧٨٩٠]/g,function(a){return og[a]}).replace(/،/g,",")},postformat:function(a){return a.replace(/\d/g,function(a){return ng[a]}).replace(/,/g,"،")},week:{dow:6,// Saturday is the first day of the week. +doy:12}}),{1:"-inci",5:"-inci",8:"-inci",70:"-inci",80:"-inci",2:"-nci",7:"-nci",20:"-nci",50:"-nci",3:"-üncü",4:"-üncü",100:"-üncü",6:"-ncı",9:"-uncu",10:"-uncu",30:"-uncu",60:"-ıncı",90:"-ıncı"}),ug=(kg.defineLocale("az",{months:"yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr".split("_"),monthsShort:"yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek".split("_"),weekdays:"Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə".split("_"),weekdaysShort:"Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən".split("_"),weekdaysMin:"Bz_BE_ÇA_Çə_CA_Cü_Şə".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[sabah saat] LT",nextWeek:"[gələn həftə] dddd [saat] LT",lastDay:"[dünən] LT",lastWeek:"[keçən həftə] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s əvvəl",s:"birneçə saniyyə",m:"bir dəqiqə",mm:"%d dəqiqə",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir il",yy:"%d il"},meridiemParse:/gecə|səhər|gündüz|axşam/,isPM:function(a){return/^(gündüz|axşam)$/.test(a)},meridiem:function(a,b,c){return 4>a?"gecə":12>a?"səhər":17>a?"gündüz":"axşam"},ordinalParse:/\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,ordinal:function(a){if(0===a)// special case for zero +return a+"-ıncı";var b=a%10,c=a%100-b,d=a>=100?100:null;return a+(tg[b]||tg[c]||tg[d])},week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("be",{months:{format:"студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня".split("_"),standalone:"студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань".split("_")},monthsShort:"студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж".split("_"),weekdays:{format:"нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу".split("_"),standalone:"нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота".split("_"),isFormat:/\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/},weekdaysShort:"нд_пн_ат_ср_чц_пт_сб".split("_"),weekdaysMin:"нд_пн_ат_ср_чц_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., HH:mm",LLLL:"dddd, D MMMM YYYY г., HH:mm"},calendar:{sameDay:"[Сёння ў] LT",nextDay:"[Заўтра ў] LT",lastDay:"[Учора ў] LT",nextWeek:function(){return"[У] dddd [ў] LT"},lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return"[У мінулую] dddd [ў] LT";case 1:case 2:case 4:return"[У мінулы] dddd [ў] LT"}},sameElse:"L"},relativeTime:{future:"праз %s",past:"%s таму",s:"некалькі секунд",m:nd,mm:nd,h:nd,hh:nd,d:"дзень",dd:nd,M:"месяц",MM:nd,y:"год",yy:nd},meridiemParse:/ночы|раніцы|дня|вечара/,isPM:function(a){return/^(дня|вечара)$/.test(a)},meridiem:function(a,b,c){return 4>a?"ночы":12>a?"раніцы":17>a?"дня":"вечара"},ordinalParse:/\d{1,2}-(і|ы|га)/,ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":case"w":case"W":return a%10!==2&&a%10!==3||a%100===12||a%100===13?a+"-ы":a+"-і";case"D":return a+"-га";default:return a}},week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("bg",{months:"януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),monthsShort:"янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"),weekdays:"неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"),weekdaysShort:"нед_пон_вто_сря_чет_пет_съб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[Днес в] LT",nextDay:"[Утре в] LT",nextWeek:"dddd [в] LT",lastDay:"[Вчера в] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[В изминалата] dddd [в] LT";case 1:case 2:case 4:case 5:return"[В изминалия] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"след %s",past:"преди %s",s:"няколко секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дни",M:"месец",MM:"%d месеца",y:"година",yy:"%d години"},ordinalParse:/\d{1,2}-(ев|ен|ти|ви|ри|ми)/,ordinal:function(a){var b=a%10,c=a%100;return 0===a?a+"-ев":0===c?a+"-ен":c>10&&20>c?a+"-ти":1===b?a+"-ви":2===b?a+"-ри":7===b||8===b?a+"-ми":a+"-ти"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),{1:"১",2:"২",3:"৩",4:"৪",5:"৫",6:"৬",7:"৭",8:"৮",9:"৯",0:"০"}),vg={"১":"1","২":"2","৩":"3","৪":"4","৫":"5","৬":"6","৭":"7","৮":"8","৯":"9","০":"0"},wg=(kg.defineLocale("bn",{months:"জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর".split("_"),monthsShort:"জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্".split("_"),weekdays:"রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রবার_শনিবার".split("_"),weekdaysShort:"রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্র_শনি".split("_"),weekdaysMin:"রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি".split("_"),longDateFormat:{LT:"A h:mm সময়",LTS:"A h:mm:ss সময়",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm সময়",LLLL:"dddd, D MMMM YYYY, A h:mm সময়"},calendar:{sameDay:"[আজ] LT",nextDay:"[আগামীকাল] LT",nextWeek:"dddd, LT",lastDay:"[গতকাল] LT",lastWeek:"[গত] dddd, LT",sameElse:"L"},relativeTime:{future:"%s পরে",past:"%s আগে",s:"কয়েক সেকেন্ড",m:"এক মিনিট",mm:"%d মিনিট",h:"এক ঘন্টা",hh:"%d ঘন্টা",d:"এক দিন",dd:"%d দিন",M:"এক মাস",MM:"%d মাস",y:"এক বছর",yy:"%d বছর"},preparse:function(a){return a.replace(/[১২৩৪৫৬৭৮৯০]/g,function(a){return vg[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return ug[a]})},meridiemParse:/রাত|সকাল|দুপুর|বিকাল|রাত/,meridiemHour:function(a,b){return 12===a&&(a=0),"রাত"===b&&a>=4||"দুপুর"===b&&5>a||"বিকাল"===b?a+12:a},meridiem:function(a,b,c){return 4>a?"রাত":10>a?"সকাল":17>a?"দুপুর":20>a?"বিকাল":"রাত"},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),{1:"༡",2:"༢",3:"༣",4:"༤",5:"༥",6:"༦",7:"༧",8:"༨",9:"༩",0:"༠"}),xg={"༡":"1","༢":"2","༣":"3","༤":"4","༥":"5","༦":"6","༧":"7","༨":"8","༩":"9","༠":"0"},yg=(kg.defineLocale("bo",{months:"ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ".split("_"),monthsShort:"ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ".split("_"),weekdays:"གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་".split("_"),weekdaysShort:"ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་".split("_"),weekdaysMin:"ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[དི་རིང] LT",nextDay:"[སང་ཉིན] LT",nextWeek:"[བདུན་ཕྲག་རྗེས་མ], LT",lastDay:"[ཁ་སང] LT",lastWeek:"[བདུན་ཕྲག་མཐའ་མ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s ལ་",past:"%s སྔན་ལ",s:"ལམ་སང",m:"སྐར་མ་གཅིག",mm:"%d སྐར་མ",h:"ཆུ་ཚོད་གཅིག",hh:"%d ཆུ་ཚོད",d:"ཉིན་གཅིག",dd:"%d ཉིན་",M:"ཟླ་བ་གཅིག",MM:"%d ཟླ་བ",y:"ལོ་གཅིག",yy:"%d ལོ"},preparse:function(a){return a.replace(/[༡༢༣༤༥༦༧༨༩༠]/g,function(a){return xg[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return wg[a]})},meridiemParse:/མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/,meridiemHour:function(a,b){return 12===a&&(a=0),"མཚན་མོ"===b&&a>=4||"ཉིན་གུང"===b&&5>a||"དགོང་དག"===b?a+12:a},meridiem:function(a,b,c){return 4>a?"མཚན་མོ":10>a?"ཞོགས་ཀས":17>a?"ཉིན་གུང":20>a?"དགོང་དག":"མཚན་མོ"},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),kg.defineLocale("br",{months:"Genver_C'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"),monthsShort:"Gen_C'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"),weekdays:"Sul_Lun_Meurzh_Merc'her_Yaou_Gwener_Sadorn".split("_"),weekdaysShort:"Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"),weekdaysMin:"Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h[e]mm A",LTS:"h[e]mm:ss A",L:"DD/MM/YYYY",LL:"D [a viz] MMMM YYYY",LLL:"D [a viz] MMMM YYYY h[e]mm A",LLLL:"dddd, D [a viz] MMMM YYYY h[e]mm A"},calendar:{sameDay:"[Hiziv da] LT",nextDay:"[Warc'hoazh da] LT",nextWeek:"dddd [da] LT",lastDay:"[Dec'h da] LT",lastWeek:"dddd [paset da] LT",sameElse:"L"},relativeTime:{future:"a-benn %s",past:"%s 'zo",s:"un nebeud segondennoù",m:"ur vunutenn",mm:od,h:"un eur",hh:"%d eur",d:"un devezh",dd:od,M:"ur miz",MM:od,y:"ur bloaz",yy:pd},ordinalParse:/\d{1,2}(añ|vet)/,ordinal:function(a){var b=1===a?"añ":"vet";return a+b},week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("bs",{months:"januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",m:td,mm:td,h:td,hh:td,d:"dan",dd:td,M:"mjesec",MM:td,y:"godinu",yy:td},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("ca",{months:"gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre".split("_"),monthsShort:"gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.".split("_"),monthsParseExact:!0,weekdays:"diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte".split("_"),weekdaysShort:"dg._dl._dt._dc._dj._dv._ds.".split("_"),weekdaysMin:"Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd D MMMM YYYY H:mm"},calendar:{sameDay:function(){return"[avui a "+(1!==this.hours()?"les":"la")+"] LT"},nextDay:function(){return"[demà a "+(1!==this.hours()?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(1!==this.hours()?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(1!==this.hours()?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(1!==this.hours()?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fa %s",s:"uns segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},ordinalParse:/\d{1,2}(r|n|t|è|a)/,ordinal:function(a,b){var c=1===a?"r":2===a?"n":3===a?"r":4===a?"t":"è";return"w"!==b&&"W"!==b||(c="a"),a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),"leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_")),zg="led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_"),Ag=(kg.defineLocale("cs",{months:yg,monthsShort:zg,monthsParse:function(a,b){var c,d=[];for(c=0;12>c;c++) +// use custom parser to solve problem with July (červenec) +d[c]=new RegExp("^"+a[c]+"$|^"+b[c]+"$","i");return d}(yg,zg),shortMonthsParse:function(a){var b,c=[];for(b=0;12>b;b++)c[b]=new RegExp("^"+a[b]+"$","i");return c}(zg),longMonthsParse:function(a){var b,c=[];for(b=0;12>b;b++)c[b]=new RegExp("^"+a[b]+"$","i");return c}(yg),weekdays:"neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"),weekdaysShort:"ne_po_út_st_čt_pá_so".split("_"),weekdaysMin:"ne_po_út_st_čt_pá_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm",l:"D. M. YYYY"},calendar:{sameDay:"[dnes v] LT",nextDay:"[zítra v] LT",nextWeek:function(){switch(this.day()){case 0:return"[v neděli v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve středu v] LT";case 4:return"[ve čtvrtek v] LT";case 5:return"[v pátek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[včera v] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulou neděli v] LT";case 1:case 2:return"[minulé] dddd [v] LT";case 3:return"[minulou středu v] LT";case 4:case 5:return"[minulý] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"před %s",s:vd,m:vd,mm:vd,h:vd,hh:vd,d:vd,dd:vd,M:vd,MM:vd,y:vd,yy:vd},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("cv",{months:"кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав".split("_"),monthsShort:"кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш".split("_"),weekdays:"вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун".split("_"),weekdaysShort:"выр_тун_ытл_юн_кӗҫ_эрн_шӑм".split("_"),weekdaysMin:"вр_тн_ыт_юн_кҫ_эр_шм".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]",LLL:"YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm",LLLL:"dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm"},calendar:{sameDay:"[Паян] LT [сехетре]",nextDay:"[Ыран] LT [сехетре]",lastDay:"[Ӗнер] LT [сехетре]",nextWeek:"[Ҫитес] dddd LT [сехетре]",lastWeek:"[Иртнӗ] dddd LT [сехетре]",sameElse:"L"},relativeTime:{future:function(a){var b=/сехет$/i.exec(a)?"рен":/ҫул$/i.exec(a)?"тан":"ран";return a+b},past:"%s каялла",s:"пӗр-ик ҫеккунт",m:"пӗр минут",mm:"%d минут",h:"пӗр сехет",hh:"%d сехет",d:"пӗр кун",dd:"%d кун",M:"пӗр уйӑх",MM:"%d уйӑх",y:"пӗр ҫул",yy:"%d ҫул"},ordinalParse:/\d{1,2}-мӗш/,ordinal:"%d-мӗш",week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("cy",{months:"Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr".split("_"),monthsShort:"Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag".split("_"),weekdays:"Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn".split("_"),weekdaysShort:"Sul_Llun_Maw_Mer_Iau_Gwe_Sad".split("_"),weekdaysMin:"Su_Ll_Ma_Me_Ia_Gw_Sa".split("_"),weekdaysParseExact:!0, +// time formats are the same as en-gb +longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Heddiw am] LT",nextDay:"[Yfory am] LT",nextWeek:"dddd [am] LT",lastDay:"[Ddoe am] LT",lastWeek:"dddd [diwethaf am] LT",sameElse:"L"},relativeTime:{future:"mewn %s",past:"%s yn ôl",s:"ychydig eiliadau",m:"munud",mm:"%d munud",h:"awr",hh:"%d awr",d:"diwrnod",dd:"%d diwrnod",M:"mis",MM:"%d mis",y:"blwyddyn",yy:"%d flynedd"},ordinalParse:/\d{1,2}(fed|ain|af|il|ydd|ed|eg)/, +// traditional ordinal numbers above 31 are not commonly used in colloquial Welsh +ordinal:function(a){var b=a,c="",d=["","af","il","ydd","ydd","ed","ed","ed","fed","fed","fed",// 1af to 10fed +"eg","fed","eg","eg","fed","eg","eg","fed","eg","fed"];return b>20?c=40===b||50===b||60===b||80===b||100===b?"fed":"ain":b>0&&(c=d[b]),a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("da",{months:"januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd [d.] D. MMMM YYYY HH:mm"},calendar:{sameDay:"[I dag kl.] LT",nextDay:"[I morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[I går kl.] LT",lastWeek:"[sidste] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"få sekunder",m:"et minut",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dage",M:"en måned",MM:"%d måneder",y:"et år",yy:"%d år"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("de-at",{months:"Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:wd,mm:"%d Minuten",h:wd,hh:"%d Stunden",d:wd,dd:wd,M:wd,MM:wd,y:wd,yy:wd},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:xd,mm:"%d Minuten",h:xd,hh:"%d Stunden",d:xd,dd:xd,M:xd,MM:xd,y:xd,yy:xd},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),["ޖެނުއަރީ","ފެބްރުއަރީ","މާރިޗު","އޭޕްރީލު","މޭ","ޖޫން","ޖުލައި","އޯގަސްޓު","ސެޕްޓެމްބަރު","އޮކްޓޯބަރު","ނޮވެމްބަރު","ޑިސެމްބަރު"]),Bg=["އާދިއްތަ","ހޯމަ","އަންގާރަ","ބުދަ","ބުރާސްފަތި","ހުކުރު","ހޮނިހިރު"],Cg=(kg.defineLocale("dv",{months:Ag,monthsShort:Ag,weekdays:Bg,weekdaysShort:Bg,weekdaysMin:"އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/M/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/މކ|މފ/,isPM:function(a){return"މފ"===a},meridiem:function(a,b,c){return 12>a?"މކ":"މފ"},calendar:{sameDay:"[މިއަދު] LT",nextDay:"[މާދަމާ] LT",nextWeek:"dddd LT",lastDay:"[އިއްޔެ] LT",lastWeek:"[ފާއިތުވި] dddd LT",sameElse:"L"},relativeTime:{future:"ތެރޭގައި %s",past:"ކުރިން %s",s:"ސިކުންތުކޮޅެއް",m:"މިނިޓެއް",mm:"މިނިޓު %d",h:"ގަޑިއިރެއް",hh:"ގަޑިއިރު %d",d:"ދުވަހެއް",dd:"ދުވަސް %d",M:"މަހެއް",MM:"މަސް %d",y:"އަހަރެއް",yy:"އަހަރު %d"},preparse:function(a){return a.replace(/،/g,",")},postformat:function(a){return a.replace(/,/g,"،")},week:{dow:7,// Sunday is the first day of the week. +doy:12}}),kg.defineLocale("el",{monthsNominativeEl:"Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"),monthsGenitiveEl:"Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"),months:function(a,b){return/D/.test(b.substring(0,b.indexOf("MMMM")))?this._monthsGenitiveEl[a.month()]:this._monthsNominativeEl[a.month()]},monthsShort:"Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"),weekdays:"Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"),weekdaysShort:"Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"),weekdaysMin:"Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"),meridiem:function(a,b,c){return a>11?c?"μμ":"ΜΜ":c?"πμ":"ΠΜ"},isPM:function(a){return"μ"===(a+"").toLowerCase()[0]},meridiemParse:/[ΠΜ]\.?Μ?\.?/i,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendarEl:{sameDay:"[Σήμερα {}] LT",nextDay:"[Αύριο {}] LT",nextWeek:"dddd [{}] LT",lastDay:"[Χθες {}] LT",lastWeek:function(){switch(this.day()){case 6:return"[το προηγούμενο] dddd [{}] LT";default:return"[την προηγούμενη] dddd [{}] LT"}},sameElse:"L"},calendar:function(a,b){var c=this._calendarEl[a],d=b&&b.hours();return y(c)&&(c=c.apply(b)),c.replace("{}",d%12===1?"στη":"στις")},relativeTime:{future:"σε %s",past:"%s πριν",s:"λίγα δευτερόλεπτα",m:"ένα λεπτό",mm:"%d λεπτά",h:"μία ώρα",hh:"%d ώρες",d:"μία μέρα",dd:"%d μέρες",M:"ένας μήνας",MM:"%d μήνες",y:"ένας χρόνος",yy:"%d χρόνια"},ordinalParse:/\d{1,2}η/,ordinal:"%dη",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("en-au",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("en-ca",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"YYYY-MM-DD",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),kg.defineLocale("en-gb",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("en-ie",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("en-nz",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("eo",{months:"januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec".split("_"),weekdays:"Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato".split("_"),weekdaysShort:"Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Ĵa_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D[-an de] MMMM, YYYY",LLL:"D[-an de] MMMM, YYYY HH:mm",LLLL:"dddd, [la] D[-an de] MMMM, YYYY HH:mm"},meridiemParse:/[ap]\.t\.m/i,isPM:function(a){return"p"===a.charAt(0).toLowerCase()},meridiem:function(a,b,c){return a>11?c?"p.t.m.":"P.T.M.":c?"a.t.m.":"A.T.M."},calendar:{sameDay:"[Hodiaŭ je] LT",nextDay:"[Morgaŭ je] LT",nextWeek:"dddd [je] LT",lastDay:"[Hieraŭ je] LT",lastWeek:"[pasinta] dddd [je] LT",sameElse:"L"},relativeTime:{future:"je %s",past:"antaŭ %s",s:"sekundoj",m:"minuto",mm:"%d minutoj",h:"horo",hh:"%d horoj",d:"tago",//ne 'diurno', ĉar estas uzita por proksimumo +dd:"%d tagoj",M:"monato",MM:"%d monatoj",y:"jaro",yy:"%d jaroj"},ordinalParse:/\d{1,2}a/,ordinal:"%da",week:{dow:1,// Monday is the first day of the week. +doy:7}}),"ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_")),Dg="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),Eg=(kg.defineLocale("es-do",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(a,b){return/-MMM-/.test(b)?Dg[a.month()]:Cg[a.month()]},monthsParseExact:!0,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY h:mm A",LLLL:"dddd, D [de] MMMM [de] YYYY h:mm A"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,// Monday is the first day of the week. +doy:4}}),"ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_")),Fg="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),Gg=(kg.defineLocale("es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(a,b){return/-MMM-/.test(b)?Fg[a.month()]:Eg[a.month()]},monthsParseExact:!0,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("et",{months:"jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"),monthsShort:"jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"),weekdays:"pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev".split("_"),weekdaysShort:"P_E_T_K_N_R_L".split("_"),weekdaysMin:"P_E_T_K_N_R_L".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[Täna,] LT",nextDay:"[Homme,] LT",nextWeek:"[Järgmine] dddd LT",lastDay:"[Eile,] LT",lastWeek:"[Eelmine] dddd LT",sameElse:"L"},relativeTime:{future:"%s pärast",past:"%s tagasi",s:yd,m:yd,mm:yd,h:yd,hh:yd,d:yd,dd:"%d päeva",M:yd,MM:yd,y:yd,yy:yd},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("eu",{months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),monthsParseExact:!0,weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY[ko] MMMM[ren] D[a]",LLL:"YYYY[ko] MMMM[ren] D[a] HH:mm",LLLL:"dddd, YYYY[ko] MMMM[ren] D[a] HH:mm",l:"YYYY-M-D",ll:"YYYY[ko] MMM D[a]",lll:"YYYY[ko] MMM D[a] HH:mm",llll:"ddd, YYYY[ko] MMM D[a] HH:mm"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),{1:"۱",2:"۲",3:"۳",4:"۴",5:"۵",6:"۶",7:"۷",8:"۸",9:"۹",0:"۰"}),Hg={"۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9","۰":"0"},Ig=(kg.defineLocale("fa",{months:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),monthsShort:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),weekdays:"یکشنبه_دوشنبه_سهشنبه_چهارشنبه_پنجشنبه_جمعه_شنبه".split("_"),weekdaysShort:"یکشنبه_دوشنبه_سهشنبه_چهارشنبه_پنجشنبه_جمعه_شنبه".split("_"),weekdaysMin:"ی_د_س_چ_پ_ج_ش".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/قبل از ظهر|بعد از ظهر/,isPM:function(a){return/بعد از ظهر/.test(a)},meridiem:function(a,b,c){return 12>a?"قبل از ظهر":"بعد از ظهر"},calendar:{sameDay:"[امروز ساعت] LT",nextDay:"[فردا ساعت] LT",nextWeek:"dddd [ساعت] LT",lastDay:"[دیروز ساعت] LT",lastWeek:"dddd [پیش] [ساعت] LT",sameElse:"L"},relativeTime:{future:"در %s",past:"%s پیش",s:"چندین ثانیه",m:"یک دقیقه",mm:"%d دقیقه",h:"یک ساعت",hh:"%d ساعت",d:"یک روز",dd:"%d روز",M:"یک ماه",MM:"%d ماه",y:"یک سال",yy:"%d سال"},preparse:function(a){return a.replace(/[۰-۹]/g,function(a){return Hg[a]}).replace(/،/g,",")},postformat:function(a){return a.replace(/\d/g,function(a){return Gg[a]}).replace(/,/g,"،")},ordinalParse:/\d{1,2}م/,ordinal:"%dم",week:{dow:6,// Saturday is the first day of the week. +doy:12}}),"nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän".split(" ")),Jg=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",Ig[7],Ig[8],Ig[9]],Kg=(kg.defineLocale("fi",{months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"Do MMMM[ta] YYYY",LLL:"Do MMMM[ta] YYYY, [klo] HH.mm",LLLL:"dddd, Do MMMM[ta] YYYY, [klo] HH.mm",l:"D.M.YYYY",ll:"Do MMM YYYY",lll:"Do MMM YYYY, [klo] HH.mm",llll:"ddd, Do MMM YYYY, [klo] HH.mm"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s:zd,m:zd,mm:zd,h:zd,hh:zd,d:zd,dd:zd,M:zd,MM:zd,y:zd,yy:zd},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("fo",{months:"januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur".split("_"),weekdaysShort:"sun_mán_týs_mik_hós_frí_ley".split("_"),weekdaysMin:"su_má_tý_mi_hó_fr_le".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D. MMMM, YYYY HH:mm"},calendar:{sameDay:"[Í dag kl.] LT",nextDay:"[Í morgin kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[Í gjár kl.] LT",lastWeek:"[síðstu] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"um %s",past:"%s síðani",s:"fá sekund",m:"ein minutt",mm:"%d minuttir",h:"ein tími",hh:"%d tímar",d:"ein dagur",dd:"%d dagar",M:"ein mánaði",MM:"%d mánaðir",y:"eitt ár",yy:"%d ár"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("fr-ca",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinalParse:/\d{1,2}(er|e)/,ordinal:function(a){return a+(1===a?"er":"e")}}),kg.defineLocale("fr-ch",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinalParse:/\d{1,2}(er|e)/,ordinal:function(a){return a+(1===a?"er":"e")},week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinalParse:/\d{1,2}(er|)/,ordinal:function(a){return a+(1===a?"er":"")},week:{dow:1,// Monday is the first day of the week. +doy:4}}),"jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.".split("_")),Lg="jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),Mg=(kg.defineLocale("fy",{months:"jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber".split("_"),monthsShort:function(a,b){return/-MMM-/.test(b)?Lg[a.month()]:Kg[a.month()]},monthsParseExact:!0,weekdays:"snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon".split("_"),weekdaysShort:"si._mo._ti._wo._to._fr._so.".split("_"),weekdaysMin:"Si_Mo_Ti_Wo_To_Fr_So".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[hjoed om] LT",nextDay:"[moarn om] LT",nextWeek:"dddd [om] LT",lastDay:"[juster om] LT",lastWeek:"[ôfrûne] dddd [om] LT",sameElse:"L"},relativeTime:{future:"oer %s",past:"%s lyn",s:"in pear sekonden",m:"ien minút",mm:"%d minuten",h:"ien oere",hh:"%d oeren",d:"ien dei",dd:"%d dagen",M:"ien moanne",MM:"%d moannen",y:"ien jier",yy:"%d jierren"},ordinalParse:/\d{1,2}(ste|de)/,ordinal:function(a){return a+(1===a||8===a||a>=20?"ste":"de")},week:{dow:1,// Monday is the first day of the week. +doy:4}}),["Am Faoilleach","An Gearran","Am Màrt","An Giblean","An Cèitean","An t-Ògmhios","An t-Iuchar","An Lùnastal","An t-Sultain","An Dàmhair","An t-Samhain","An Dùbhlachd"]),Ng=["Faoi","Gear","Màrt","Gibl","Cèit","Ògmh","Iuch","Lùn","Sult","Dàmh","Samh","Dùbh"],Og=["Didòmhnaich","Diluain","Dimàirt","Diciadain","Diardaoin","Dihaoine","Disathairne"],Pg=["Did","Dil","Dim","Dic","Dia","Dih","Dis"],Qg=["Dò","Lu","Mà","Ci","Ar","Ha","Sa"],Rg=(kg.defineLocale("gd",{months:Mg,monthsShort:Ng,monthsParseExact:!0,weekdays:Og,weekdaysShort:Pg,weekdaysMin:Qg,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[An-diugh aig] LT",nextDay:"[A-màireach aig] LT",nextWeek:"dddd [aig] LT",lastDay:"[An-dè aig] LT",lastWeek:"dddd [seo chaidh] [aig] LT",sameElse:"L"},relativeTime:{future:"ann an %s",past:"bho chionn %s",s:"beagan diogan",m:"mionaid",mm:"%d mionaidean",h:"uair",hh:"%d uairean",d:"latha",dd:"%d latha",M:"mìos",MM:"%d mìosan",y:"bliadhna",yy:"%d bliadhna"},ordinalParse:/\d{1,2}(d|na|mh)/,ordinal:function(a){var b=1===a?"d":a%10===2?"na":"mh";return a+b},week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("gl",{months:"Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro".split("_"),monthsShort:"Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"),monthsParseExact:!0,weekdays:"Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"),weekdaysShort:"Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd D MMMM YYYY H:mm"},calendar:{sameDay:function(){return"[hoxe "+(1!==this.hours()?"ás":"á")+"] LT"},nextDay:function(){return"[mañá "+(1!==this.hours()?"ás":"á")+"] LT"},nextWeek:function(){return"dddd ["+(1!==this.hours()?"ás":"a")+"] LT"},lastDay:function(){return"[onte "+(1!==this.hours()?"á":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(1!==this.hours()?"ás":"a")+"] LT"},sameElse:"L"},relativeTime:{future:function(a){return"uns segundos"===a?"nuns segundos":"en "+a},past:"hai %s",s:"uns segundos",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("he",{months:"ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר".split("_"),monthsShort:"ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳".split("_"),weekdays:"ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת".split("_"),weekdaysShort:"א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"),weekdaysMin:"א_ב_ג_ד_ה_ו_ש".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [ב]MMMM YYYY",LLL:"D [ב]MMMM YYYY HH:mm",LLLL:"dddd, D [ב]MMMM YYYY HH:mm",l:"D/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[היום ב־]LT",nextDay:"[מחר ב־]LT",nextWeek:"dddd [בשעה] LT",lastDay:"[אתמול ב־]LT",lastWeek:"[ביום] dddd [האחרון בשעה] LT",sameElse:"L"},relativeTime:{future:"בעוד %s",past:"לפני %s",s:"מספר שניות",m:"דקה",mm:"%d דקות",h:"שעה",hh:function(a){return 2===a?"שעתיים":a+" שעות"},d:"יום",dd:function(a){return 2===a?"יומיים":a+" ימים"},M:"חודש",MM:function(a){return 2===a?"חודשיים":a+" חודשים"},y:"שנה",yy:function(a){return 2===a?"שנתיים":a%10===0&&10!==a?a+" שנה":a+" שנים"}},meridiemParse:/אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,isPM:function(a){return/^(אחה"צ|אחרי הצהריים|בערב)$/.test(a)},meridiem:function(a,b,c){return 5>a?"לפנות בוקר":10>a?"בבוקר":12>a?c?'לפנה"צ':"לפני הצהריים":18>a?c?'אחה"צ':"אחרי הצהריים":"בערב"}}),{1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"}),Sg={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"},Tg=(kg.defineLocale("hi",{months:"जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर".split("_"),monthsShort:"जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.".split("_"),monthsParseExact:!0,weekdays:"रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm बजे",LTS:"A h:mm:ss बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm बजे",LLLL:"dddd, D MMMM YYYY, A h:mm बजे"},calendar:{sameDay:"[आज] LT",nextDay:"[कल] LT",nextWeek:"dddd, LT",lastDay:"[कल] LT",lastWeek:"[पिछले] dddd, LT",sameElse:"L"},relativeTime:{future:"%s में",past:"%s पहले",s:"कुछ ही क्षण",m:"एक मिनट",mm:"%d मिनट",h:"एक घंटा",hh:"%d घंटे",d:"एक दिन",dd:"%d दिन",M:"एक महीने",MM:"%d महीने",y:"एक वर्ष",yy:"%d वर्ष"},preparse:function(a){return a.replace(/[१२३४५६७८९०]/g,function(a){return Sg[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return Rg[a]})}, +// Hindi notation for meridiems are quite fuzzy in practice. While there exists +// a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi. +meridiemParse:/रात|सुबह|दोपहर|शाम/,meridiemHour:function(a,b){return 12===a&&(a=0),"रात"===b?4>a?a:a+12:"सुबह"===b?a:"दोपहर"===b?a>=10?a:a+12:"शाम"===b?a+12:void 0},meridiem:function(a,b,c){return 4>a?"रात":10>a?"सुबह":17>a?"दोपहर":20>a?"शाम":"रात"},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),kg.defineLocale("hr",{months:{format:"siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca".split("_"),standalone:"siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_")},monthsShort:"sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",m:Bd,mm:Bd,h:Bd,hh:Bd,d:"dan",dd:Bd,M:"mjesec",MM:Bd,y:"godinu",yy:Bd},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),"vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton".split(" ")),Ug=(kg.defineLocale("hu",{months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),weekdays:"vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"vas_hét_kedd_sze_csüt_pén_szo".split("_"),weekdaysMin:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D. H:mm",LLLL:"YYYY. MMMM D., dddd H:mm"},meridiemParse:/de|du/i,isPM:function(a){return"u"===a.charAt(1).toLowerCase()},meridiem:function(a,b,c){return 12>a?c===!0?"de":"DE":c===!0?"du":"DU"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return Dd.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return Dd.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:Cd,m:Cd,mm:Cd,h:Cd,hh:Cd,d:Cd,dd:Cd,M:Cd,MM:Cd,y:Cd,yy:Cd},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("hy-am",{months:{format:"հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի".split("_"),standalone:"հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր".split("_")},monthsShort:"հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ".split("_"),weekdays:"կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ".split("_"),weekdaysShort:"կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),weekdaysMin:"կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY թ.",LLL:"D MMMM YYYY թ., HH:mm",LLLL:"dddd, D MMMM YYYY թ., HH:mm"},calendar:{sameDay:"[այսօր] LT",nextDay:"[վաղը] LT",lastDay:"[երեկ] LT",nextWeek:function(){return"dddd [օրը ժամը] LT"},lastWeek:function(){return"[անցած] dddd [օրը ժամը] LT"},sameElse:"L"},relativeTime:{future:"%s հետո",past:"%s առաջ",s:"մի քանի վայրկյան",m:"րոպե",mm:"%d րոպե",h:"ժամ",hh:"%d ժամ",d:"օր",dd:"%d օր",M:"ամիս",MM:"%d ամիս",y:"տարի",yy:"%d տարի"},meridiemParse:/գիշերվա|առավոտվա|ցերեկվա|երեկոյան/,isPM:function(a){return/^(ցերեկվա|երեկոյան)$/.test(a)},meridiem:function(a){return 4>a?"գիշերվա":12>a?"առավոտվա":17>a?"ցերեկվա":"երեկոյան"},ordinalParse:/\d{1,2}|\d{1,2}-(ին|րդ)/,ordinal:function(a,b){switch(b){case"DDD":case"w":case"W":case"DDDo":return 1===a?a+"-ին":a+"-րդ";default:return a}},week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|siang|sore|malam/,meridiemHour:function(a,b){return 12===a&&(a=0),"pagi"===b?a:"siang"===b?a>=11?a:a+12:"sore"===b||"malam"===b?a+12:void 0},meridiem:function(a,b,c){return 11>a?"pagi":15>a?"siang":19>a?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("is",{months:"janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),monthsShort:"jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),weekdays:"sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),weekdaysShort:"sun_mán_þri_mið_fim_fös_lau".split("_"),weekdaysMin:"Su_Má_Þr_Mi_Fi_Fö_La".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd, D. MMMM YYYY [kl.] H:mm"},calendar:{sameDay:"[í dag kl.] LT",nextDay:"[á morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[í gær kl.] LT",lastWeek:"[síðasta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s síðan",s:Fd,m:Fd,mm:Fd,h:"klukkustund",hh:Fd,d:Fd,dd:Fd,M:Fd,MM:Fd,y:Fd,yy:Fd},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("it",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),weekdaysShort:"Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),weekdaysMin:"Do_Lu_Ma_Me_Gi_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:function(){switch(this.day()){case 0:return"[la scorsa] dddd [alle] LT";default:return"[lo scorso] dddd [alle] LT"}},sameElse:"L"},relativeTime:{future:function(a){return(/^[0-9].+$/.test(a)?"tra":"in")+" "+a},past:"%s fa",s:"alcuni secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("ja",{months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",LTS:"Ah時m分s秒",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日Ah時m分",LLLL:"YYYY年M月D日Ah時m分 dddd"},meridiemParse:/午前|午後/i,isPM:function(a){return"午後"===a},meridiem:function(a,b,c){return 12>a?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},ordinalParse:/\d{1,2}日/,ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"日";default:return a}},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"}}),kg.defineLocale("jv",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des".split("_"),weekdays:"Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu".split("_"),weekdaysShort:"Min_Sen_Sel_Reb_Kem_Jem_Sep".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sp".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/enjing|siyang|sonten|ndalu/,meridiemHour:function(a,b){return 12===a&&(a=0),"enjing"===b?a:"siyang"===b?a>=11?a:a+12:"sonten"===b||"ndalu"===b?a+12:void 0},meridiem:function(a,b,c){return 11>a?"enjing":15>a?"siyang":19>a?"sonten":"ndalu"},calendar:{sameDay:"[Dinten puniko pukul] LT",nextDay:"[Mbenjang pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kala wingi pukul] LT",lastWeek:"dddd [kepengker pukul] LT",sameElse:"L"},relativeTime:{future:"wonten ing %s",past:"%s ingkang kepengker",s:"sawetawis detik",m:"setunggal menit",mm:"%d menit",h:"setunggal jam",hh:"%d jam",d:"sedinten",dd:"%d dinten",M:"sewulan",MM:"%d wulan",y:"setaun",yy:"%d taun"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("ka",{months:{standalone:"იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი".split("_"),format:"იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს".split("_")},monthsShort:"იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ".split("_"),weekdays:{standalone:"კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი".split("_"),format:"კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს".split("_"),isFormat:/(წინა|შემდეგ)/},weekdaysShort:"კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ".split("_"),weekdaysMin:"კვ_ორ_სა_ოთ_ხუ_პა_შა".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[დღეს] LT[-ზე]",nextDay:"[ხვალ] LT[-ზე]",lastDay:"[გუშინ] LT[-ზე]",nextWeek:"[შემდეგ] dddd LT[-ზე]",lastWeek:"[წინა] dddd LT-ზე",sameElse:"L"},relativeTime:{future:function(a){return/(წამი|წუთი|საათი|წელი)/.test(a)?a.replace(/ი$/,"ში"):a+"ში"},past:function(a){return/(წამი|წუთი|საათი|დღე|თვე)/.test(a)?a.replace(/(ი|ე)$/,"ის წინ"):/წელი/.test(a)?a.replace(/წელი$/,"წლის წინ"):void 0},s:"რამდენიმე წამი",m:"წუთი",mm:"%d წუთი",h:"საათი",hh:"%d საათი",d:"დღე",dd:"%d დღე",M:"თვე",MM:"%d თვე",y:"წელი",yy:"%d წელი"},ordinalParse:/0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/,ordinal:function(a){return 0===a?a:1===a?a+"-ლი":20>a||100>=a&&a%20===0||a%100===0?"მე-"+a:a+"-ე"},week:{dow:1,doy:7}}),{0:"-ші",1:"-ші",2:"-ші",3:"-ші",4:"-ші",5:"-ші",6:"-шы",7:"-ші",8:"-ші",9:"-шы",10:"-шы",20:"-шы",30:"-шы",40:"-шы",50:"-ші",60:"-шы",70:"-ші",80:"-ші",90:"-шы",100:"-ші"}),Vg=(kg.defineLocale("kk",{months:"қаңтар_ақпан_наурыз_сәуір_мамыр_маусым_шілде_тамыз_қыркүйек_қазан_қараша_желтоқсан".split("_"),monthsShort:"қаң_ақп_нау_сәу_мам_мау_шіл_там_қыр_қаз_қар_жел".split("_"),weekdays:"жексенбі_дүйсенбі_сейсенбі_сәрсенбі_бейсенбі_жұма_сенбі".split("_"),weekdaysShort:"жек_дүй_сей_сәр_бей_жұм_сен".split("_"),weekdaysMin:"жк_дй_сй_ср_бй_жм_сн".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Бүгін сағат] LT",nextDay:"[Ертең сағат] LT",nextWeek:"dddd [сағат] LT",lastDay:"[Кеше сағат] LT",lastWeek:"[Өткен аптаның] dddd [сағат] LT",sameElse:"L"},relativeTime:{future:"%s ішінде",past:"%s бұрын",s:"бірнеше секунд",m:"бір минут",mm:"%d минут",h:"бір сағат",hh:"%d сағат",d:"бір күн",dd:"%d күн",M:"бір ай",MM:"%d ай",y:"бір жыл",yy:"%d жыл"},ordinalParse:/\d{1,2}-(ші|шы)/,ordinal:function(a){var b=a%10,c=a>=100?100:null;return a+(Ug[a]||Ug[b]||Ug[c])},week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("km",{months:"មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ".split("_"),monthsShort:"មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ".split("_"),weekdays:"អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍".split("_"),weekdaysShort:"អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍".split("_"),weekdaysMin:"អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[ថ្ងៃនេះ ម៉ោង] LT",nextDay:"[ស្អែក ម៉ោង] LT",nextWeek:"dddd [ម៉ោង] LT",lastDay:"[ម្សិលមិញ ម៉ោង] LT",lastWeek:"dddd [សប្តាហ៍មុន] [ម៉ោង] LT",sameElse:"L"},relativeTime:{future:"%sទៀត",past:"%sមុន",s:"ប៉ុន្មានវិនាទី",m:"មួយនាទី",mm:"%d នាទី",h:"មួយម៉ោង",hh:"%d ម៉ោង",d:"មួយថ្ងៃ",dd:"%d ថ្ងៃ",M:"មួយខែ",MM:"%d ខែ",y:"មួយឆ្នាំ",yy:"%d ឆ្នាំ"},week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("ko",{months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h시 m분",LTS:"A h시 m분 s초",L:"YYYY.MM.DD",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 A h시 m분",LLLL:"YYYY년 MMMM D일 dddd A h시 m분"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇 초",ss:"%d초",m:"일분",mm:"%d분",h:"한 시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한 달",MM:"%d달",y:"일 년",yy:"%d년"},ordinalParse:/\d{1,2}일/,ordinal:"%d일",meridiemParse:/오전|오후/,isPM:function(a){return"오후"===a},meridiem:function(a,b,c){return 12>a?"오전":"오후"}}),{0:"-чү",1:"-чи",2:"-чи",3:"-чү",4:"-чү",5:"-чи",6:"-чы",7:"-чи",8:"-чи",9:"-чу",10:"-чу",20:"-чы",30:"-чу",40:"-чы",50:"-чү",60:"-чы",70:"-чи",80:"-чи",90:"-чу",100:"-чү"}),Wg=(kg.defineLocale("ky",{months:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_"),monthsShort:"янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек".split("_"),weekdays:"Жекшемби_Дүйшөмбү_Шейшемби_Шаршемби_Бейшемби_Жума_Ишемби".split("_"),weekdaysShort:"Жек_Дүй_Шей_Шар_Бей_Жум_Ише".split("_"),weekdaysMin:"Жк_Дй_Шй_Шр_Бй_Жм_Иш".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Бүгүн саат] LT",nextDay:"[Эртең саат] LT",nextWeek:"dddd [саат] LT",lastDay:"[Кече саат] LT",lastWeek:"[Өткен аптанын] dddd [күнү] [саат] LT",sameElse:"L"},relativeTime:{future:"%s ичинде",past:"%s мурун",s:"бирнече секунд",m:"бир мүнөт",mm:"%d мүнөт",h:"бир саат",hh:"%d саат",d:"бир күн",dd:"%d күн",M:"бир ай",MM:"%d ай",y:"бир жыл",yy:"%d жыл"},ordinalParse:/\d{1,2}-(чи|чы|чү|чу)/,ordinal:function(a){var b=a%10,c=a>=100?100:null;return a+(Vg[a]||Vg[b]||Vg[c])},week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("lb",{months:"Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg".split("_"),weekdaysShort:"So._Mé._Dë._Më._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mé_Dë_Më_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm [Auer]",LTS:"H:mm:ss [Auer]",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm [Auer]",LLLL:"dddd, D. MMMM YYYY H:mm [Auer]"},calendar:{sameDay:"[Haut um] LT",sameElse:"L",nextDay:"[Muer um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gëschter um] LT",lastWeek:function(){ +// Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule +switch(this.day()){case 2:case 4:return"[Leschten] dddd [um] LT";default:return"[Leschte] dddd [um] LT"}}},relativeTime:{future:Hd,past:Id,s:"e puer Sekonnen",m:Gd,mm:"%d Minutten",h:Gd,hh:"%d Stonnen",d:Gd,dd:"%d Deeg",M:Gd,MM:"%d Méint",y:Gd,yy:"%d Joer"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("lo",{months:"ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ".split("_"),monthsShort:"ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ".split("_"),weekdays:"ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ".split("_"),weekdaysShort:"ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ".split("_"),weekdaysMin:"ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"ວັນdddd D MMMM YYYY HH:mm"},meridiemParse:/ຕອນເຊົ້າ|ຕອນແລງ/,isPM:function(a){return"ຕອນແລງ"===a},meridiem:function(a,b,c){return 12>a?"ຕອນເຊົ້າ":"ຕອນແລງ"},calendar:{sameDay:"[ມື້ນີ້ເວລາ] LT",nextDay:"[ມື້ອື່ນເວລາ] LT",nextWeek:"[ວັນ]dddd[ໜ້າເວລາ] LT",lastDay:"[ມື້ວານນີ້ເວລາ] LT",lastWeek:"[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT",sameElse:"L"},relativeTime:{future:"ອີກ %s",past:"%sຜ່ານມາ",s:"ບໍ່ເທົ່າໃດວິນາທີ",m:"1 ນາທີ",mm:"%d ນາທີ",h:"1 ຊົ່ວໂມງ",hh:"%d ຊົ່ວໂມງ",d:"1 ມື້",dd:"%d ມື້",M:"1 ເດືອນ",MM:"%d ເດືອນ",y:"1 ປີ",yy:"%d ປີ"},ordinalParse:/(ທີ່)\d{1,2}/,ordinal:function(a){return"ທີ່"+a}}),{m:"minutė_minutės_minutę",mm:"minutės_minučių_minutes",h:"valanda_valandos_valandą",hh:"valandos_valandų_valandas",d:"diena_dienos_dieną",dd:"dienos_dienų_dienas",M:"mėnuo_mėnesio_mėnesį",MM:"mėnesiai_mėnesių_mėnesius",y:"metai_metų_metus",yy:"metai_metų_metus"}),Xg=(kg.defineLocale("lt",{months:{format:"sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio".split("_"),standalone:"sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis".split("_"),isFormat:/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?|MMMM?(\[[^\[\]]*\]|\s+)+D[oD]?/},monthsShort:"sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd".split("_"),weekdays:{format:"sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį".split("_"),standalone:"sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis".split("_"),isFormat:/dddd HH:mm/},weekdaysShort:"Sek_Pir_Ant_Tre_Ket_Pen_Šeš".split("_"),weekdaysMin:"S_P_A_T_K_Pn_Š".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY [m.] MMMM D [d.]",LLL:"YYYY [m.] MMMM D [d.], HH:mm [val.]",LLLL:"YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]",l:"YYYY-MM-DD",ll:"YYYY [m.] MMMM D [d.]",lll:"YYYY [m.] MMMM D [d.], HH:mm [val.]",llll:"YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]"},calendar:{sameDay:"[Šiandien] LT",nextDay:"[Rytoj] LT",nextWeek:"dddd LT",lastDay:"[Vakar] LT",lastWeek:"[Praėjusį] dddd LT",sameElse:"L"},relativeTime:{future:"po %s",past:"prieš %s",s:Kd,m:Ld,mm:Od,h:Ld,hh:Od,d:Ld,dd:Od,M:Ld,MM:Od,y:Ld,yy:Od},ordinalParse:/\d{1,2}-oji/,ordinal:function(a){return a+"-oji"},week:{dow:1,// Monday is the first day of the week. +doy:4}}),{m:"minūtes_minūtēm_minūte_minūtes".split("_"),mm:"minūtes_minūtēm_minūte_minūtes".split("_"),h:"stundas_stundām_stunda_stundas".split("_"),hh:"stundas_stundām_stunda_stundas".split("_"),d:"dienas_dienām_diena_dienas".split("_"),dd:"dienas_dienām_diena_dienas".split("_"),M:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),MM:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),y:"gada_gadiem_gads_gadi".split("_"),yy:"gada_gadiem_gads_gadi".split("_")}),Yg=(kg.defineLocale("lv",{months:"janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris".split("_"),monthsShort:"jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec".split("_"),weekdays:"svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena".split("_"),weekdaysShort:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysMin:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY.",LL:"YYYY. [gada] D. MMMM",LLL:"YYYY. [gada] D. MMMM, HH:mm",LLLL:"YYYY. [gada] D. MMMM, dddd, HH:mm"},calendar:{sameDay:"[Šodien pulksten] LT",nextDay:"[Rīt pulksten] LT",nextWeek:"dddd [pulksten] LT",lastDay:"[Vakar pulksten] LT",lastWeek:"[Pagājušā] dddd [pulksten] LT",sameElse:"L"},relativeTime:{future:"pēc %s",past:"pirms %s",s:Sd,m:Rd,mm:Qd,h:Rd,hh:Qd,d:Rd,dd:Qd,M:Rd,MM:Qd,y:Rd,yy:Qd},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),{words:{//Different grammatical cases +m:["jedan minut","jednog minuta"],mm:["minut","minuta","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],dd:["dan","dana","dana"],MM:["mjesec","mjeseca","mjeseci"],yy:["godina","godine","godina"]},correctGrammaticalCase:function(a,b){return 1===a?b[0]:a>=2&&4>=a?b[1]:b[2]},translate:function(a,b,c){var d=Yg.words[c];return 1===c.length?b?d[0]:d[1]:a+" "+Yg.correctGrammaticalCase(a,d)}}),Zg=(kg.defineLocale("me",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sjutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){var a=["[prošle] [nedjelje] [u] LT","[prošlog] [ponedjeljka] [u] LT","[prošlog] [utorka] [u] LT","[prošle] [srijede] [u] LT","[prošlog] [četvrtka] [u] LT","[prošlog] [petka] [u] LT","[prošle] [subote] [u] LT"];return a[this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"nekoliko sekundi",m:Yg.translate,mm:Yg.translate,h:Yg.translate,hh:Yg.translate,d:"dan",dd:Yg.translate,M:"mjesec",MM:Yg.translate,y:"godinu",yy:Yg.translate},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("mk",{months:"јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември".split("_"),monthsShort:"јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек".split("_"),weekdays:"недела_понеделник_вторник_среда_четврток_петок_сабота".split("_"),weekdaysShort:"нед_пон_вто_сре_чет_пет_саб".split("_"),weekdaysMin:"нe_пo_вт_ср_че_пе_сa".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[Денес во] LT",nextDay:"[Утре во] LT",nextWeek:"[Во] dddd [во] LT",lastDay:"[Вчера во] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[Изминатата] dddd [во] LT";case 1:case 2:case 4:case 5:return"[Изминатиот] dddd [во] LT"}},sameElse:"L"},relativeTime:{future:"после %s",past:"пред %s",s:"неколку секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дена",M:"месец",MM:"%d месеци",y:"година",yy:"%d години"},ordinalParse:/\d{1,2}-(ев|ен|ти|ви|ри|ми)/,ordinal:function(a){var b=a%10,c=a%100;return 0===a?a+"-ев":0===c?a+"-ен":c>10&&20>c?a+"-ти":1===b?a+"-ви":2===b?a+"-ри":7===b||8===b?a+"-ми":a+"-ти"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("ml",{months:"ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ".split("_"),monthsShort:"ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.".split("_"),monthsParseExact:!0,weekdays:"ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച".split("_"),weekdaysShort:"ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി".split("_"),weekdaysMin:"ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ".split("_"),longDateFormat:{LT:"A h:mm -നു",LTS:"A h:mm:ss -നു",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm -നു",LLLL:"dddd, D MMMM YYYY, A h:mm -നു"},calendar:{sameDay:"[ഇന്ന്] LT",nextDay:"[നാളെ] LT",nextWeek:"dddd, LT",lastDay:"[ഇന്നലെ] LT",lastWeek:"[കഴിഞ്ഞ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s കഴിഞ്ഞ്",past:"%s മുൻപ്",s:"അൽപ നിമിഷങ്ങൾ",m:"ഒരു മിനിറ്റ്",mm:"%d മിനിറ്റ്",h:"ഒരു മണിക്കൂർ",hh:"%d മണിക്കൂർ",d:"ഒരു ദിവസം",dd:"%d ദിവസം",M:"ഒരു മാസം",MM:"%d മാസം",y:"ഒരു വർഷം",yy:"%d വർഷം"},meridiemParse:/രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i,meridiemHour:function(a,b){return 12===a&&(a=0),"രാത്രി"===b&&a>=4||"ഉച്ച കഴിഞ്ഞ്"===b||"വൈകുന്നേരം"===b?a+12:a},meridiem:function(a,b,c){return 4>a?"രാത്രി":12>a?"രാവിലെ":17>a?"ഉച്ച കഴിഞ്ഞ്":20>a?"വൈകുന്നേരം":"രാത്രി"}}),{1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"}),$g={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"},_g=(kg.defineLocale("mr",{months:"जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर".split("_"),monthsShort:"जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.".split("_"),monthsParseExact:!0,weekdays:"रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm वाजता",LTS:"A h:mm:ss वाजता",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm वाजता",LLLL:"dddd, D MMMM YYYY, A h:mm वाजता"},calendar:{sameDay:"[आज] LT",nextDay:"[उद्या] LT",nextWeek:"dddd, LT",lastDay:"[काल] LT",lastWeek:"[मागील] dddd, LT",sameElse:"L"},relativeTime:{future:"%sमध्ये",past:"%sपूर्वी",s:Td,m:Td,mm:Td,h:Td,hh:Td,d:Td,dd:Td,M:Td,MM:Td,y:Td,yy:Td},preparse:function(a){return a.replace(/[१२३४५६७८९०]/g,function(a){return $g[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return Zg[a]})},meridiemParse:/रात्री|सकाळी|दुपारी|सायंकाळी/,meridiemHour:function(a,b){return 12===a&&(a=0),"रात्री"===b?4>a?a:a+12:"सकाळी"===b?a:"दुपारी"===b?a>=10?a:a+12:"सायंकाळी"===b?a+12:void 0},meridiem:function(a,b,c){return 4>a?"रात्री":10>a?"सकाळी":17>a?"दुपारी":20>a?"सायंकाळी":"रात्री"},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),kg.defineLocale("ms-my",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|tengahari|petang|malam/,meridiemHour:function(a,b){return 12===a&&(a=0),"pagi"===b?a:"tengahari"===b?a>=11?a:a+12:"petang"===b||"malam"===b?a+12:void 0},meridiem:function(a,b,c){return 11>a?"pagi":15>a?"tengahari":19>a?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("ms",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|tengahari|petang|malam/,meridiemHour:function(a,b){return 12===a&&(a=0),"pagi"===b?a:"tengahari"===b?a>=11?a:a+12:"petang"===b||"malam"===b?a+12:void 0},meridiem:function(a,b,c){return 11>a?"pagi":15>a?"tengahari":19>a?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),{1:"၁",2:"၂",3:"၃",4:"၄",5:"၅",6:"၆",7:"၇",8:"၈",9:"၉",0:"၀"}),ah={"၁":"1","၂":"2","၃":"3","၄":"4","၅":"5","၆":"6","၇":"7","၈":"8","၉":"9","၀":"0"},bh=(kg.defineLocale("my",{months:"ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ".split("_"),monthsShort:"ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ".split("_"),weekdays:"တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ".split("_"),weekdaysShort:"နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ".split("_"),weekdaysMin:"နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[ယနေ.] LT [မှာ]",nextDay:"[မနက်ဖြန်] LT [မှာ]",nextWeek:"dddd LT [မှာ]",lastDay:"[မနေ.က] LT [မှာ]",lastWeek:"[ပြီးခဲ့သော] dddd LT [မှာ]",sameElse:"L"},relativeTime:{future:"လာမည့် %s မှာ",past:"လွန်ခဲ့သော %s က",s:"စက္ကန်.အနည်းငယ်",m:"တစ်မိနစ်",mm:"%d မိနစ်",h:"တစ်နာရီ",hh:"%d နာရီ",d:"တစ်ရက်",dd:"%d ရက်",M:"တစ်လ",MM:"%d လ",y:"တစ်နှစ်",yy:"%d နှစ်"},preparse:function(a){return a.replace(/[၁၂၃၄၅၆၇၈၉၀]/g,function(a){return ah[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return _g[a]})},week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("nb",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.".split("_"),monthsParseExact:!0,weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"sø._ma._ti._on._to._fr._lø.".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] HH:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[i går kl.] LT",lastWeek:"[forrige] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"noen sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en måned",MM:"%d måneder",y:"ett år",yy:"%d år"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),{1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"}),ch={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"},dh=(kg.defineLocale("ne",{months:"जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर".split("_"),monthsShort:"जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.".split("_"),monthsParseExact:!0,weekdays:"आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार".split("_"),weekdaysShort:"आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.".split("_"),weekdaysMin:"आ._सो._मं._बु._बि._शु._श.".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"Aको h:mm बजे",LTS:"Aको h:mm:ss बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, Aको h:mm बजे",LLLL:"dddd, D MMMM YYYY, Aको h:mm बजे"},preparse:function(a){return a.replace(/[१२३४५६७८९०]/g,function(a){return ch[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return bh[a]})},meridiemParse:/राति|बिहान|दिउँसो|साँझ/,meridiemHour:function(a,b){return 12===a&&(a=0),"राति"===b?4>a?a:a+12:"बिहान"===b?a:"दिउँसो"===b?a>=10?a:a+12:"साँझ"===b?a+12:void 0},meridiem:function(a,b,c){return 3>a?"राति":12>a?"बिहान":16>a?"दिउँसो":20>a?"साँझ":"राति"},calendar:{sameDay:"[आज] LT",nextDay:"[भोलि] LT",nextWeek:"[आउँदो] dddd[,] LT",lastDay:"[हिजो] LT",lastWeek:"[गएको] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%sमा",past:"%s अगाडि",s:"केही क्षण",m:"एक मिनेट",mm:"%d मिनेट",h:"एक घण्टा",hh:"%d घण्टा",d:"एक दिन",dd:"%d दिन",M:"एक महिना",MM:"%d महिना",y:"एक बर्ष",yy:"%d बर्ष"},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),"jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_")),eh="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),fh=(kg.defineLocale("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(a,b){return/-MMM-/.test(b)?eh[a.month()]:dh[a.month()]},monthsParseExact:!0,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},ordinalParse:/\d{1,2}(ste|de)/,ordinal:function(a){return a+(1===a||8===a||a>=20?"ste":"de")},week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("nn",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),weekdaysShort:"sun_mån_tys_ons_tor_fre_lau".split("_"),weekdaysMin:"su_må_ty_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[I dag klokka] LT",nextDay:"[I morgon klokka] LT",nextWeek:"dddd [klokka] LT",lastDay:"[I går klokka] LT",lastWeek:"[Føregåande] dddd [klokka] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s sidan",s:"nokre sekund",m:"eit minutt",mm:"%d minutt",h:"ein time",hh:"%d timar",d:"ein dag",dd:"%d dagar",M:"ein månad",MM:"%d månader",y:"eit år",yy:"%d år"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),{1:"੧",2:"੨",3:"੩",4:"੪",5:"੫",6:"੬",7:"੭",8:"੮",9:"੯",0:"੦"}),gh={"੧":"1","੨":"2","੩":"3","੪":"4","੫":"5","੬":"6","੭":"7","੮":"8","੯":"9","੦":"0"},hh=(kg.defineLocale("pa-in",{ +// There are months name as per Nanakshahi Calender but they are not used as rigidly in modern Punjabi. +months:"ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ".split("_"),monthsShort:"ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ".split("_"),weekdays:"ਐਤਵਾਰ_ਸੋਮਵਾਰ_ਮੰਗਲਵਾਰ_ਬੁਧਵਾਰ_ਵੀਰਵਾਰ_ਸ਼ੁੱਕਰਵਾਰ_ਸ਼ਨੀਚਰਵਾਰ".split("_"),weekdaysShort:"ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ".split("_"),weekdaysMin:"ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ".split("_"),longDateFormat:{LT:"A h:mm ਵਜੇ",LTS:"A h:mm:ss ਵਜੇ",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm ਵਜੇ",LLLL:"dddd, D MMMM YYYY, A h:mm ਵਜੇ"},calendar:{sameDay:"[ਅਜ] LT",nextDay:"[ਕਲ] LT",nextWeek:"dddd, LT",lastDay:"[ਕਲ] LT",lastWeek:"[ਪਿਛਲੇ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s ਵਿੱਚ",past:"%s ਪਿਛਲੇ",s:"ਕੁਝ ਸਕਿੰਟ",m:"ਇਕ ਮਿੰਟ",mm:"%d ਮਿੰਟ",h:"ਇੱਕ ਘੰਟਾ",hh:"%d ਘੰਟੇ",d:"ਇੱਕ ਦਿਨ",dd:"%d ਦਿਨ",M:"ਇੱਕ ਮਹੀਨਾ",MM:"%d ਮਹੀਨੇ",y:"ਇੱਕ ਸਾਲ",yy:"%d ਸਾਲ"},preparse:function(a){return a.replace(/[੧੨੩੪੫੬੭੮੯੦]/g,function(a){return gh[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return fh[a]})}, +// Punjabi notation for meridiems are quite fuzzy in practice. While there exists +// a rigid notion of a 'Pahar' it is not used as rigidly in modern Punjabi. +meridiemParse:/ਰਾਤ|ਸਵੇਰ|ਦੁਪਹਿਰ|ਸ਼ਾਮ/,meridiemHour:function(a,b){return 12===a&&(a=0),"ਰਾਤ"===b?4>a?a:a+12:"ਸਵੇਰ"===b?a:"ਦੁਪਹਿਰ"===b?a>=10?a:a+12:"ਸ਼ਾਮ"===b?a+12:void 0},meridiem:function(a,b,c){return 4>a?"ਰਾਤ":10>a?"ਸਵੇਰ":17>a?"ਦੁਪਹਿਰ":20>a?"ਸ਼ਾਮ":"ਰਾਤ"},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),"styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_")),ih="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_"),jh=(kg.defineLocale("pl",{months:function(a,b){return""===b?"("+ih[a.month()]+"|"+hh[a.month()]+")":/D MMMM/.test(b)?ih[a.month()]:hh[a.month()]},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"nie_pon_wt_śr_czw_pt_sb".split("_"),weekdaysMin:"Nd_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:"[W] dddd [o] LT",lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zeszłą niedzielę o] LT";case 3:return"[W zeszłą środę o] LT";case 6:return"[W zeszłą sobotę o] LT";default:return"[W zeszły] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",m:Vd,mm:Vd,h:Vd,hh:Vd,d:"1 dzień",dd:"%d dni",M:"miesiąc",MM:Vd,y:"rok",yy:Vd},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("pt-br",{months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY [às] HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY [às] HH:mm"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){// Saturday + Sunday +return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"poucos segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº"}),kg.defineLocale("pt",{months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-Feira_Terça-Feira_Quarta-Feira_Quinta-Feira_Sexta-Feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY HH:mm"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){// Saturday + Sunday +return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"há %s",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("ro",{months:"ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie".split("_"),monthsShort:"ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"duminică_luni_marți_miercuri_joi_vineri_sâmbătă".split("_"),weekdaysShort:"Dum_Lun_Mar_Mie_Joi_Vin_Sâm".split("_"),weekdaysMin:"Du_Lu_Ma_Mi_Jo_Vi_Sâ".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[azi la] LT",nextDay:"[mâine la] LT",nextWeek:"dddd [la] LT",lastDay:"[ieri la] LT",lastWeek:"[fosta] dddd [la] LT",sameElse:"L"},relativeTime:{future:"peste %s",past:"%s în urmă",s:"câteva secunde",m:"un minut",mm:Wd,h:"o oră",hh:Wd,d:"o zi",dd:Wd,M:"o lună",MM:Wd,y:"un an",yy:Wd},week:{dow:1,// Monday is the first day of the week. +doy:7}}),[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[йя]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i]),kh=(kg.defineLocale("ru",{months:{format:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_"),standalone:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_")},monthsShort:{ +// по CLDR именно "июл." и "июн.", но какой смысл менять букву на точку ? +format:"янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.".split("_"),standalone:"янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.".split("_")},weekdays:{standalone:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),format:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_"),isFormat:/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/},weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:jh,longMonthsParse:jh,shortMonthsParse:jh, +// полные названия с падежами, по три буквы, для некоторых, по 4 буквы, сокращения с точкой и без точки +monthsRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i, +// копия предыдущего +monthsShortRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i, +// полные названия с падежами +monthsStrictRegex:/^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i, +// Выражение, которое соотвествует только сокращённым формам +monthsShortStrictRegex:/^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., HH:mm",LLLL:"dddd, D MMMM YYYY г., HH:mm"},calendar:{sameDay:"[Сегодня в] LT",nextDay:"[Завтра в] LT",lastDay:"[Вчера в] LT",nextWeek:function(a){if(a.week()===this.week())return 2===this.day()?"[Во] dddd [в] LT":"[В] dddd [в] LT";switch(this.day()){case 0:return"[В следующее] dddd [в] LT";case 1:case 2:case 4:return"[В следующий] dddd [в] LT";case 3:case 5:case 6:return"[В следующую] dddd [в] LT"}},lastWeek:function(a){if(a.week()===this.week())return 2===this.day()?"[Во] dddd [в] LT":"[В] dddd [в] LT";switch(this.day()){case 0:return"[В прошлое] dddd [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",m:Yd,mm:Yd,h:"час",hh:Yd,d:"день",dd:Yd,M:"месяц",MM:Yd,y:"год",yy:Yd},meridiemParse:/ночи|утра|дня|вечера/i,isPM:function(a){return/^(дня|вечера)$/.test(a)},meridiem:function(a,b,c){return 4>a?"ночи":12>a?"утра":17>a?"дня":"вечера"},ordinalParse:/\d{1,2}-(й|го|я)/,ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":return a+"-й";case"D":return a+"-го";case"w":case"W":return a+"-я";default:return a}},week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("se",{months:"ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu".split("_"),monthsShort:"ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov".split("_"),weekdays:"sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat".split("_"),weekdaysShort:"sotn_vuos_maŋ_gask_duor_bear_láv".split("_"),weekdaysMin:"s_v_m_g_d_b_L".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"MMMM D. [b.] YYYY",LLL:"MMMM D. [b.] YYYY [ti.] HH:mm",LLLL:"dddd, MMMM D. [b.] YYYY [ti.] HH:mm"},calendar:{sameDay:"[otne ti] LT",nextDay:"[ihttin ti] LT",nextWeek:"dddd [ti] LT",lastDay:"[ikte ti] LT",lastWeek:"[ovddit] dddd [ti] LT",sameElse:"L"},relativeTime:{future:"%s geažes",past:"maŋit %s",s:"moadde sekunddat",m:"okta minuhta",mm:"%d minuhtat",h:"okta diimmu",hh:"%d diimmut",d:"okta beaivi",dd:"%d beaivvit",M:"okta mánnu",MM:"%d mánut",y:"okta jahki",yy:"%d jagit"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("si",{months:"ජනවාරි_පෙබරවාරි_මාර්තු_අප්රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්".split("_"),monthsShort:"ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ".split("_"),weekdays:"ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා".split("_"),weekdaysShort:"ඉරි_සඳු_අඟ_බදා_බ්රහ_සිකු_සෙන".split("_"),weekdaysMin:"ඉ_ස_අ_බ_බ්ර_සි_සෙ".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"a h:mm",LTS:"a h:mm:ss",L:"YYYY/MM/DD",LL:"YYYY MMMM D",LLL:"YYYY MMMM D, a h:mm",LLLL:"YYYY MMMM D [වැනි] dddd, a h:mm:ss"},calendar:{sameDay:"[අද] LT[ට]",nextDay:"[හෙට] LT[ට]",nextWeek:"dddd LT[ට]",lastDay:"[ඊයේ] LT[ට]",lastWeek:"[පසුගිය] dddd LT[ට]",sameElse:"L"},relativeTime:{future:"%sකින්",past:"%sකට පෙර",s:"තත්පර කිහිපය",m:"මිනිත්තුව",mm:"මිනිත්තු %d",h:"පැය",hh:"පැය %d",d:"දිනය",dd:"දින %d",M:"මාසය",MM:"මාස %d",y:"වසර",yy:"වසර %d"},ordinalParse:/\d{1,2} වැනි/,ordinal:function(a){return a+" වැනි"},meridiemParse:/පෙර වරු|පස් වරු|පෙ.ව|ප.ව./,isPM:function(a){return"ප.ව."===a||"පස් වරු"===a},meridiem:function(a,b,c){return a>11?c?"ප.ව.":"පස් වරු":c?"පෙ.ව.":"පෙර වරු"}}),"január_február_marec_apríl_máj_jún_júl_august_september_október_november_december".split("_")),lh="jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec".split("_"),mh=(kg.defineLocale("sk",{months:kh,monthsShort:lh,weekdays:"nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota".split("_"),weekdaysShort:"ne_po_ut_st_št_pi_so".split("_"),weekdaysMin:"ne_po_ut_st_št_pi_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm"},calendar:{sameDay:"[dnes o] LT",nextDay:"[zajtra o] LT",nextWeek:function(){switch(this.day()){case 0:return"[v nedeľu o] LT";case 1:case 2:return"[v] dddd [o] LT";case 3:return"[v stredu o] LT";case 4:return"[vo štvrtok o] LT";case 5:return"[v piatok o] LT";case 6:return"[v sobotu o] LT"}},lastDay:"[včera o] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulú nedeľu o] LT";case 1:case 2:return"[minulý] dddd [o] LT";case 3:return"[minulú stredu o] LT";case 4:case 5:return"[minulý] dddd [o] LT";case 6:return"[minulú sobotu o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pred %s",s:$d,m:$d,mm:$d,h:$d,hh:$d,d:$d,dd:$d,M:$d,MM:$d,y:$d,yy:$d},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("sl",{months:"januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota".split("_"),weekdaysShort:"ned._pon._tor._sre._čet._pet._sob.".split("_"),weekdaysMin:"ne_po_to_sr_če_pe_so".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danes ob] LT",nextDay:"[jutri ob] LT",nextWeek:function(){switch(this.day()){case 0:return"[v] [nedeljo] [ob] LT";case 3:return"[v] [sredo] [ob] LT";case 6:return"[v] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[v] dddd [ob] LT"}},lastDay:"[včeraj ob] LT",lastWeek:function(){switch(this.day()){case 0:return"[prejšnjo] [nedeljo] [ob] LT";case 3:return"[prejšnjo] [sredo] [ob] LT";case 6:return"[prejšnjo] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[prejšnji] dddd [ob] LT"}},sameElse:"L"},relativeTime:{future:"čez %s",past:"pred %s",s:_d,m:_d,mm:_d,h:_d,hh:_d,d:_d,dd:_d,M:_d,MM:_d,y:_d,yy:_d},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("sq",{months:"Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor".split("_"),monthsShort:"Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj".split("_"),weekdays:"E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë".split("_"),weekdaysShort:"Die_Hën_Mar_Mër_Enj_Pre_Sht".split("_"),weekdaysMin:"D_H_Ma_Më_E_P_Sh".split("_"),weekdaysParseExact:!0,meridiemParse:/PD|MD/,isPM:function(a){return"M"===a.charAt(0)},meridiem:function(a,b,c){return 12>a?"PD":"MD"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Sot në] LT",nextDay:"[Nesër në] LT",nextWeek:"dddd [në] LT",lastDay:"[Dje në] LT",lastWeek:"dddd [e kaluar në] LT",sameElse:"L"},relativeTime:{future:"në %s",past:"%s më parë",s:"disa sekonda",m:"një minutë",mm:"%d minuta",h:"një orë",hh:"%d orë",d:"një ditë",dd:"%d ditë",M:"një muaj",MM:"%d muaj",y:"një vit",yy:"%d vite"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),{words:{//Different grammatical cases +m:["један минут","једне минуте"],mm:["минут","минуте","минута"],h:["један сат","једног сата"],hh:["сат","сата","сати"],dd:["дан","дана","дана"],MM:["месец","месеца","месеци"],yy:["година","године","година"]},correctGrammaticalCase:function(a,b){return 1===a?b[0]:a>=2&&4>=a?b[1]:b[2]},translate:function(a,b,c){var d=mh.words[c];return 1===c.length?b?d[0]:d[1]:a+" "+mh.correctGrammaticalCase(a,d)}}),nh=(kg.defineLocale("sr-cyrl",{months:"јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар".split("_"),monthsShort:"јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.".split("_"),monthsParseExact:!0,weekdays:"недеља_понедељак_уторак_среда_четвртак_петак_субота".split("_"),weekdaysShort:"нед._пон._уто._сре._чет._пет._суб.".split("_"),weekdaysMin:"не_по_ут_ср_че_пе_су".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[данас у] LT",nextDay:"[сутра у] LT",nextWeek:function(){switch(this.day()){case 0:return"[у] [недељу] [у] LT";case 3:return"[у] [среду] [у] LT";case 6:return"[у] [суботу] [у] LT";case 1:case 2:case 4:case 5:return"[у] dddd [у] LT"}},lastDay:"[јуче у] LT",lastWeek:function(){var a=["[прошле] [недеље] [у] LT","[прошлог] [понедељка] [у] LT","[прошлог] [уторка] [у] LT","[прошле] [среде] [у] LT","[прошлог] [четвртка] [у] LT","[прошлог] [петка] [у] LT","[прошле] [суботе] [у] LT"];return a[this.day()]},sameElse:"L"},relativeTime:{future:"за %s",past:"пре %s",s:"неколико секунди",m:mh.translate,mm:mh.translate,h:mh.translate,hh:mh.translate,d:"дан",dd:mh.translate,M:"месец",MM:mh.translate,y:"годину",yy:mh.translate},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),{words:{//Different grammatical cases +m:["jedan minut","jedne minute"],mm:["minut","minute","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],dd:["dan","dana","dana"],MM:["mesec","meseca","meseci"],yy:["godina","godine","godina"]},correctGrammaticalCase:function(a,b){return 1===a?b[0]:a>=2&&4>=a?b[1]:b[2]},translate:function(a,b,c){var d=nh.words[c];return 1===c.length?b?d[0]:d[1]:a+" "+nh.correctGrammaticalCase(a,d)}}),oh=(kg.defineLocale("sr",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sre._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedelju] [u] LT";case 3:return"[u] [sredu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){var a=["[prošle] [nedelje] [u] LT","[prošlog] [ponedeljka] [u] LT","[prošlog] [utorka] [u] LT","[prošle] [srede] [u] LT","[prošlog] [četvrtka] [u] LT","[prošlog] [petka] [u] LT","[prošle] [subote] [u] LT"];return a[this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"pre %s",s:"nekoliko sekundi",m:nh.translate,mm:nh.translate,h:nh.translate,hh:nh.translate,d:"dan",dd:nh.translate,M:"mesec",MM:nh.translate,y:"godinu",yy:nh.translate},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("ss",{months:"Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split("_"),monthsShort:"Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo".split("_"),weekdays:"Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo".split("_"),weekdaysShort:"Lis_Umb_Lsb_Les_Lsi_Lsh_Umg".split("_"),weekdaysMin:"Li_Us_Lb_Lt_Ls_Lh_Ug".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Namuhla nga] LT",nextDay:"[Kusasa nga] LT",nextWeek:"dddd [nga] LT",lastDay:"[Itolo nga] LT",lastWeek:"dddd [leliphelile] [nga] LT",sameElse:"L"},relativeTime:{future:"nga %s",past:"wenteka nga %s",s:"emizuzwana lomcane",m:"umzuzu",mm:"%d emizuzu",h:"lihora",hh:"%d emahora",d:"lilanga",dd:"%d emalanga",M:"inyanga",MM:"%d tinyanga",y:"umnyaka",yy:"%d iminyaka"},meridiemParse:/ekuseni|emini|entsambama|ebusuku/,meridiem:function(a,b,c){return 11>a?"ekuseni":15>a?"emini":19>a?"entsambama":"ebusuku"},meridiemHour:function(a,b){return 12===a&&(a=0),"ekuseni"===b?a:"emini"===b?a>=11?a:a+12:"entsambama"===b||"ebusuku"===b?0===a?0:a+12:void 0},ordinalParse:/\d{1,2}/,ordinal:"%d",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("sv",{months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),weekdaysShort:"sön_mån_tis_ons_tor_fre_lör".split("_"),weekdaysMin:"sö_må_ti_on_to_fr_lö".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [kl.] HH:mm",LLLL:"dddd D MMMM YYYY [kl.] HH:mm",lll:"D MMM YYYY HH:mm",llll:"ddd D MMM YYYY HH:mm"},calendar:{sameDay:"[Idag] LT",nextDay:"[Imorgon] LT",lastDay:"[Igår] LT",nextWeek:"[På] dddd LT",lastWeek:"[I] dddd[s] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"för %s sedan",s:"några sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en månad",MM:"%d månader",y:"ett år",yy:"%d år"},ordinalParse:/\d{1,2}(e|a)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"e":1===b?"a":2===b?"a":"e";return a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("sw",{months:"Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des".split("_"),weekdays:"Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi".split("_"),weekdaysShort:"Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos".split("_"),weekdaysMin:"J2_J3_J4_J5_Al_Ij_J1".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[leo saa] LT",nextDay:"[kesho saa] LT",nextWeek:"[wiki ijayo] dddd [saat] LT",lastDay:"[jana] LT",lastWeek:"[wiki iliyopita] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s baadaye",past:"tokea %s",s:"hivi punde",m:"dakika moja",mm:"dakika %d",h:"saa limoja",hh:"masaa %d",d:"siku moja",dd:"masiku %d",M:"mwezi mmoja",MM:"miezi %d",y:"mwaka mmoja",yy:"miaka %d"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),{1:"௧",2:"௨",3:"௩",4:"௪",5:"௫",6:"௬",7:"௭",8:"௮",9:"௯",0:"௦"}),ph={"௧":"1","௨":"2","௩":"3","௪":"4","௫":"5","௬":"6","௭":"7","௮":"8","௯":"9","௦":"0"},qh=(kg.defineLocale("ta",{months:"ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்".split("_"),monthsShort:"ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்".split("_"),weekdays:"ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை".split("_"),weekdaysShort:"ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி".split("_"),weekdaysMin:"ஞா_தி_செ_பு_வி_வெ_ச".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, HH:mm",LLLL:"dddd, D MMMM YYYY, HH:mm"},calendar:{sameDay:"[இன்று] LT",nextDay:"[நாளை] LT",nextWeek:"dddd, LT",lastDay:"[நேற்று] LT",lastWeek:"[கடந்த வாரம்] dddd, LT",sameElse:"L"},relativeTime:{future:"%s இல்",past:"%s முன்",s:"ஒரு சில விநாடிகள்",m:"ஒரு நிமிடம்",mm:"%d நிமிடங்கள்",h:"ஒரு மணி நேரம்",hh:"%d மணி நேரம்",d:"ஒரு நாள்",dd:"%d நாட்கள்",M:"ஒரு மாதம்",MM:"%d மாதங்கள்",y:"ஒரு வருடம்",yy:"%d ஆண்டுகள்"},ordinalParse:/\d{1,2}வது/,ordinal:function(a){return a+"வது"},preparse:function(a){return a.replace(/[௧௨௩௪௫௬௭௮௯௦]/g,function(a){return ph[a]})},postformat:function(a){return a.replace(/\d/g,function(a){return oh[a]})}, +// refer http://ta.wikipedia.org/s/1er1 +meridiemParse:/யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/,meridiem:function(a,b,c){return 2>a?" யாமம்":6>a?" வைகறை":10>a?" காலை":14>a?" நண்பகல்":18>a?" எற்பாடு":22>a?" மாலை":" யாமம்"},meridiemHour:function(a,b){return 12===a&&(a=0),"யாமம்"===b?2>a?a:a+12:"வைகறை"===b||"காலை"===b?a:"நண்பகல்"===b&&a>=10?a:a+12},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),kg.defineLocale("te",{months:"జనవరి_ఫిబ్రవరి_మార్చి_ఏప్రిల్_మే_జూన్_జూలై_ఆగస్టు_సెప్టెంబర్_అక్టోబర్_నవంబర్_డిసెంబర్".split("_"),monthsShort:"జన._ఫిబ్ర._మార్చి_ఏప్రి._మే_జూన్_జూలై_ఆగ._సెప్._అక్టో._నవ._డిసె.".split("_"),monthsParseExact:!0,weekdays:"ఆదివారం_సోమవారం_మంగళవారం_బుధవారం_గురువారం_శుక్రవారం_శనివారం".split("_"),weekdaysShort:"ఆది_సోమ_మంగళ_బుధ_గురు_శుక్ర_శని".split("_"),weekdaysMin:"ఆ_సో_మం_బు_గు_శు_శ".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm",LLLL:"dddd, D MMMM YYYY, A h:mm"},calendar:{sameDay:"[నేడు] LT",nextDay:"[రేపు] LT",nextWeek:"dddd, LT",lastDay:"[నిన్న] LT",lastWeek:"[గత] dddd, LT",sameElse:"L"},relativeTime:{future:"%s లో",past:"%s క్రితం",s:"కొన్ని క్షణాలు",m:"ఒక నిమిషం",mm:"%d నిమిషాలు",h:"ఒక గంట",hh:"%d గంటలు",d:"ఒక రోజు",dd:"%d రోజులు",M:"ఒక నెల",MM:"%d నెలలు",y:"ఒక సంవత్సరం",yy:"%d సంవత్సరాలు"},ordinalParse:/\d{1,2}వ/,ordinal:"%dవ",meridiemParse:/రాత్రి|ఉదయం|మధ్యాహ్నం|సాయంత్రం/,meridiemHour:function(a,b){return 12===a&&(a=0),"రాత్రి"===b?4>a?a:a+12:"ఉదయం"===b?a:"మధ్యాహ్నం"===b?a>=10?a:a+12:"సాయంత్రం"===b?a+12:void 0},meridiem:function(a,b,c){return 4>a?"రాత్రి":10>a?"ఉదయం":17>a?"మధ్యాహ్నం":20>a?"సాయంత్రం":"రాత్రి"},week:{dow:0,// Sunday is the first day of the week. +doy:6}}),kg.defineLocale("th",{months:"มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"),monthsShort:"ม.ค._ก.พ._มี.ค._เม.ย._พ.ค._มิ.ย._ก.ค._ส.ค._ก.ย._ต.ค._พ.ย._ธ.ค.".split("_"),monthsParseExact:!0,weekdays:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"),weekdaysShort:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"),// yes, three characters difference +weekdaysMin:"อา._จ._อ._พ._พฤ._ศ._ส.".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H นาฬิกา m นาที",LTS:"H นาฬิกา m นาที s วินาที",L:"YYYY/MM/DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY เวลา H นาฬิกา m นาที",LLLL:"วันddddที่ D MMMM YYYY เวลา H นาฬิกา m นาที"},meridiemParse:/ก่อนเที่ยง|หลังเที่ยง/,isPM:function(a){return"หลังเที่ยง"===a},meridiem:function(a,b,c){return 12>a?"ก่อนเที่ยง":"หลังเที่ยง"},calendar:{sameDay:"[วันนี้ เวลา] LT",nextDay:"[พรุ่งนี้ เวลา] LT",nextWeek:"dddd[หน้า เวลา] LT",lastDay:"[เมื่อวานนี้ เวลา] LT",lastWeek:"[วัน]dddd[ที่แล้ว เวลา] LT",sameElse:"L"},relativeTime:{future:"อีก %s",past:"%sที่แล้ว",s:"ไม่กี่วินาที",m:"1 นาที",mm:"%d นาที",h:"1 ชั่วโมง",hh:"%d ชั่วโมง",d:"1 วัน",dd:"%d วัน",M:"1 เดือน",MM:"%d เดือน",y:"1 ปี",yy:"%d ปี"}}),kg.defineLocale("tl-ph",{months:"Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre".split("_"),monthsShort:"Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis".split("_"),weekdays:"Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado".split("_"),weekdaysShort:"Lin_Lun_Mar_Miy_Huw_Biy_Sab".split("_"),weekdaysMin:"Li_Lu_Ma_Mi_Hu_Bi_Sab".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"MM/D/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY HH:mm",LLLL:"dddd, MMMM DD, YYYY HH:mm"},calendar:{sameDay:"[Ngayon sa] LT",nextDay:"[Bukas sa] LT",nextWeek:"dddd [sa] LT",lastDay:"[Kahapon sa] LT",lastWeek:"dddd [huling linggo] LT",sameElse:"L"},relativeTime:{future:"sa loob ng %s",past:"%s ang nakalipas",s:"ilang segundo",m:"isang minuto",mm:"%d minuto",h:"isang oras",hh:"%d oras",d:"isang araw",dd:"%d araw",M:"isang buwan",MM:"%d buwan",y:"isang taon",yy:"%d taon"},ordinalParse:/\d{1,2}/,ordinal:function(a){return a},week:{dow:1,// Monday is the first day of the week. +doy:4}}),"pagh_wa’_cha’_wej_loS_vagh_jav_Soch_chorgh_Hut".split("_")),rh=(kg.defineLocale("tlh",{months:"tera’ jar wa’_tera’ jar cha’_tera’ jar wej_tera’ jar loS_tera’ jar vagh_tera’ jar jav_tera’ jar Soch_tera’ jar chorgh_tera’ jar Hut_tera’ jar wa’maH_tera’ jar wa’maH wa’_tera’ jar wa’maH cha’".split("_"),monthsShort:"jar wa’_jar cha’_jar wej_jar loS_jar vagh_jar jav_jar Soch_jar chorgh_jar Hut_jar wa’maH_jar wa’maH wa’_jar wa’maH cha’".split("_"),monthsParseExact:!0,weekdays:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),weekdaysShort:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),weekdaysMin:"lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[DaHjaj] LT",nextDay:"[wa’leS] LT",nextWeek:"LLL",lastDay:"[wa’Hu’] LT",lastWeek:"LLL",sameElse:"L"},relativeTime:{future:ae,past:be,s:"puS lup",m:"wa’ tup",mm:ce,h:"wa’ rep",hh:ce,d:"wa’ jaj",dd:ce,M:"wa’ jar",MM:ce,y:"wa’ DIS",yy:ce},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),{1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'üncü",4:"'üncü",100:"'üncü",6:"'ncı",9:"'uncu",10:"'uncu",30:"'uncu",60:"'ıncı",90:"'ıncı"}),sh=(kg.defineLocale("tr",{months:"Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"),monthsShort:"Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"),weekdaysMin:"Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[yarın saat] LT",nextWeek:"[haftaya] dddd [saat] LT",lastDay:"[dün] LT",lastWeek:"[geçen hafta] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s önce",s:"birkaç saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir yıl",yy:"%d yıl"},ordinalParse:/\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,ordinal:function(a){if(0===a)// special case for zero +return a+"'ıncı";var b=a%10,c=a%100-b,d=a>=100?100:null;return a+(rh[b]||rh[c]||rh[d])},week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("tzl",{months:"Januar_Fevraglh_Març_Avrïu_Mai_Gün_Julia_Guscht_Setemvar_Listopäts_Noemvar_Zecemvar".split("_"),monthsShort:"Jan_Fev_Mar_Avr_Mai_Gün_Jul_Gus_Set_Lis_Noe_Zec".split("_"),weekdays:"Súladi_Lúneçi_Maitzi_Márcuri_Xhúadi_Viénerçi_Sáturi".split("_"),weekdaysShort:"Súl_Lún_Mai_Már_Xhú_Vié_Sát".split("_"),weekdaysMin:"Sú_Lú_Ma_Má_Xh_Vi_Sá".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"D. MMMM [dallas] YYYY",LLL:"D. MMMM [dallas] YYYY HH.mm",LLLL:"dddd, [li] D. MMMM [dallas] YYYY HH.mm"},meridiemParse:/d\'o|d\'a/i,isPM:function(a){return"d'o"===a.toLowerCase()},meridiem:function(a,b,c){return a>11?c?"d'o":"D'O":c?"d'a":"D'A"},calendar:{sameDay:"[oxhi à] LT",nextDay:"[demà à] LT",nextWeek:"dddd [à] LT",lastDay:"[ieiri à] LT",lastWeek:"[sür el] dddd [lasteu à] LT",sameElse:"L"},relativeTime:{future:"osprei %s",past:"ja%s",s:ee,m:ee,mm:ee,h:ee,hh:ee,d:ee,dd:ee,M:ee,MM:ee,y:ee,yy:ee},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("tzm-latn",{months:"innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),monthsShort:"innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),weekdays:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),weekdaysShort:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),weekdaysMin:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[asdkh g] LT",nextDay:"[aska g] LT",nextWeek:"dddd [g] LT",lastDay:"[assant g] LT",lastWeek:"dddd [g] LT",sameElse:"L"},relativeTime:{future:"dadkh s yan %s",past:"yan %s",s:"imik",m:"minuḍ",mm:"%d minuḍ",h:"saɛa",hh:"%d tassaɛin",d:"ass",dd:"%d ossan",M:"ayowr",MM:"%d iyyirn",y:"asgas",yy:"%d isgasn"},week:{dow:6,// Saturday is the first day of the week. +doy:12}}),kg.defineLocale("tzm",{months:"ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),monthsShort:"ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),weekdays:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),weekdaysShort:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),weekdaysMin:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[ⴰⵙⴷⵅ ⴴ] LT",nextDay:"[ⴰⵙⴽⴰ ⴴ] LT",nextWeek:"dddd [ⴴ] LT",lastDay:"[ⴰⵚⴰⵏⵜ ⴴ] LT",lastWeek:"dddd [ⴴ] LT",sameElse:"L"},relativeTime:{future:"ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s",past:"ⵢⴰⵏ %s",s:"ⵉⵎⵉⴽ",m:"ⵎⵉⵏⵓⴺ",mm:"%d ⵎⵉⵏⵓⴺ",h:"ⵙⴰⵄⴰ",hh:"%d ⵜⴰⵙⵙⴰⵄⵉⵏ",d:"ⴰⵙⵙ",dd:"%d oⵙⵙⴰⵏ",M:"ⴰⵢoⵓⵔ",MM:"%d ⵉⵢⵢⵉⵔⵏ",y:"ⴰⵙⴳⴰⵙ",yy:"%d ⵉⵙⴳⴰⵙⵏ"},week:{dow:6,// Saturday is the first day of the week. +doy:12}}),kg.defineLocale("uk",{months:{format:"січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня".split("_"),standalone:"січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень".split("_")},monthsShort:"січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),weekdays:he,weekdaysShort:"нд_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY р.",LLL:"D MMMM YYYY р., HH:mm",LLLL:"dddd, D MMMM YYYY р., HH:mm"},calendar:{sameDay:ie("[Сьогодні "),nextDay:ie("[Завтра "),lastDay:ie("[Вчора "),nextWeek:ie("[У] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return ie("[Минулої] dddd [").call(this);case 1:case 2:case 4:return ie("[Минулого] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"за %s",past:"%s тому",s:"декілька секунд",m:ge,mm:ge,h:"годину",hh:ge,d:"день",dd:ge,M:"місяць",MM:ge,y:"рік",yy:ge}, +// M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason +meridiemParse:/ночі|ранку|дня|вечора/,isPM:function(a){return/^(дня|вечора)$/.test(a)},meridiem:function(a,b,c){return 4>a?"ночі":12>a?"ранку":17>a?"дня":"вечора"},ordinalParse:/\d{1,2}-(й|го)/,ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":case"w":case"W":return a+"-й";case"D":return a+"-го";default:return a}},week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("uz",{months:"январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр".split("_"),monthsShort:"янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек".split("_"),weekdays:"Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба".split("_"),weekdaysShort:"Якш_Душ_Сеш_Чор_Пай_Жум_Шан".split("_"),weekdaysMin:"Як_Ду_Се_Чо_Па_Жу_Ша".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"D MMMM YYYY, dddd HH:mm"},calendar:{sameDay:"[Бугун соат] LT [да]",nextDay:"[Эртага] LT [да]",nextWeek:"dddd [куни соат] LT [да]",lastDay:"[Кеча соат] LT [да]",lastWeek:"[Утган] dddd [куни соат] LT [да]",sameElse:"L"},relativeTime:{future:"Якин %s ичида",past:"Бир неча %s олдин",s:"фурсат",m:"бир дакика",mm:"%d дакика",h:"бир соат",hh:"%d соат",d:"бир кун",dd:"%d кун",M:"бир ой",MM:"%d ой",y:"бир йил",yy:"%d йил"},week:{dow:1,// Monday is the first day of the week. +doy:7}}),kg.defineLocale("vi",{months:"tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12".split("_"),monthsShort:"Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12".split("_"),monthsParseExact:!0,weekdays:"chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy".split("_"),weekdaysShort:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysMin:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysParseExact:!0,meridiemParse:/sa|ch/i,isPM:function(a){return/^ch$/i.test(a)},meridiem:function(a,b,c){return 12>a?c?"sa":"SA":c?"ch":"CH"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [năm] YYYY",LLL:"D MMMM [năm] YYYY HH:mm",LLLL:"dddd, D MMMM [năm] YYYY HH:mm",l:"DD/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[Hôm nay lúc] LT",nextDay:"[Ngày mai lúc] LT",nextWeek:"dddd [tuần tới lúc] LT",lastDay:"[Hôm qua lúc] LT",lastWeek:"dddd [tuần rồi lúc] LT",sameElse:"L"},relativeTime:{future:"%s tới",past:"%s trước",s:"vài giây",m:"một phút",mm:"%d phút",h:"một giờ",hh:"%d giờ",d:"một ngày",dd:"%d ngày",M:"một tháng",MM:"%d tháng",y:"một năm",yy:"%d năm"},ordinalParse:/\d{1,2}/,ordinal:function(a){return a},week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("x-pseudo",{months:"J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér".split("_"),monthsShort:"J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc".split("_"),monthsParseExact:!0,weekdays:"S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý".split("_"),weekdaysShort:"S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát".split("_"),weekdaysMin:"S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[T~ódá~ý át] LT",nextDay:"[T~ómó~rró~w át] LT",nextWeek:"dddd [át] LT",lastDay:"[Ý~ést~érdá~ý át] LT",lastWeek:"[L~ást] dddd [át] LT",sameElse:"L"},relativeTime:{future:"í~ñ %s",past:"%s á~gó",s:"á ~féw ~sécó~ñds",m:"á ~míñ~úté",mm:"%d m~íñú~tés",h:"á~ñ hó~úr",hh:"%d h~óúrs",d:"á ~dáý",dd:"%d d~áýs",M:"á ~móñ~th",MM:"%d m~óñt~hs",y:"á ~ýéár",yy:"%d ý~éárs"},ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("zh-cn",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah点mm分",LTS:"Ah点m分s秒",L:"YYYY-MM-DD",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日Ah点mm分",LLLL:"YYYY年MMMD日ddddAh点mm分",l:"YYYY-MM-DD",ll:"YYYY年MMMD日",lll:"YYYY年MMMD日Ah点mm分",llll:"YYYY年MMMD日ddddAh点mm分"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(a,b){return 12===a&&(a=0),"凌晨"===b||"早上"===b||"上午"===b?a:"下午"===b||"晚上"===b?a+12:a>=11?a:a+12},meridiem:function(a,b,c){var d=100*a+b;return 600>d?"凌晨":900>d?"早上":1130>d?"上午":1230>d?"中午":1800>d?"下午":"晚上"},calendar:{sameDay:function(){return 0===this.minutes()?"[今天]Ah[点整]":"[今天]LT"},nextDay:function(){return 0===this.minutes()?"[明天]Ah[点整]":"[明天]LT"},lastDay:function(){return 0===this.minutes()?"[昨天]Ah[点整]":"[昨天]LT"},nextWeek:function(){var a,b;return a=kg().startOf("week"),b=this.diff(a,"days")>=7?"[下]":"[本]",0===this.minutes()?b+"dddAh点整":b+"dddAh点mm"},lastWeek:function(){var a,b;return a=kg().startOf("week"),b=this.unix()<a.unix()?"[上]":"[本]",0===this.minutes()?b+"dddAh点整":b+"dddAh点mm"},sameElse:"LL"},ordinalParse:/\d{1,2}(日|月|周)/,ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"日";case"M":return a+"月";case"w":case"W":return a+"周";default:return a}},relativeTime:{future:"%s内",past:"%s前",s:"几秒",m:"1 分钟",mm:"%d 分钟",h:"1 小时",hh:"%d 小时",d:"1 天",dd:"%d 天",M:"1 个月",MM:"%d 个月",y:"1 年",yy:"%d 年"},week:{ +// GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效 +dow:1,// Monday is the first day of the week. +doy:4}}),kg.defineLocale("zh-tw",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah點mm分",LTS:"Ah點m分s秒",L:"YYYY年MMMD日",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日Ah點mm分",LLLL:"YYYY年MMMD日ddddAh點mm分",l:"YYYY年MMMD日",ll:"YYYY年MMMD日",lll:"YYYY年MMMD日Ah點mm分",llll:"YYYY年MMMD日ddddAh點mm分"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(a,b){return 12===a&&(a=0),"凌晨"===b||"早上"===b||"上午"===b?a:"中午"===b?a>=11?a:a+12:"下午"===b||"晚上"===b?a+12:void 0},meridiem:function(a,b,c){var d=100*a+b;return 600>d?"凌晨":900>d?"早上":1130>d?"上午":1230>d?"中午":1800>d?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},ordinalParse:/\d{1,2}(日|月|週)/,ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"日";case"M":return a+"月";case"w":case"W":return a+"週";default:return a}},relativeTime:{future:"%s內",past:"%s前",s:"幾秒",m:"1 分鐘",mm:"%d 分鐘",h:"1 小時",hh:"%d 小時",d:"1 天",dd:"%d 天",M:"1 個月",MM:"%d 個月",y:"1 年",yy:"%d 年"}}),kg);return sh.locale("en"),sh});
@@ -0,0 +1,492 @@
+//! moment.js +//! version : 2.14.1 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com +!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return md.apply(null,arguments)} +// This is done to register the method called with moment() +// without creating circular dependencies. +function b(a){md=a}function c(a){return a instanceof Array||"[object Array]"===Object.prototype.toString.call(a)}function d(a){return"[object Object]"===Object.prototype.toString.call(a)}function e(a){var b;for(b in a) +// even if its not own property I'd still call it non-empty +return!1;return!0}function f(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function g(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function h(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function i(a,b){for(var c in b)h(b,c)&&(a[c]=b[c]);return h(b,"toString")&&(a.toString=b.toString),h(b,"valueOf")&&(a.valueOf=b.valueOf),a}function j(a,b,c,d){return qb(a,b,c,d,!0).utc()}function k(){ +// We need to deep clone this object. +return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null}}function l(a){return null==a._pf&&(a._pf=k()),a._pf}function m(a){if(null==a._isValid){var b=l(a),c=nd.call(b.parsedDateParts,function(a){return null!=a});a._isValid=!isNaN(a._d.getTime())&&b.overflow<0&&!b.empty&&!b.invalidMonth&&!b.invalidWeekday&&!b.nullInput&&!b.invalidFormat&&!b.userInvalidated&&(!b.meridiem||b.meridiem&&c),a._strict&&(a._isValid=a._isValid&&0===b.charsLeftOver&&0===b.unusedTokens.length&&void 0===b.bigHour)}return a._isValid}function n(a){var b=j(NaN);return null!=a?i(l(b),a):l(b).userInvalidated=!0,b}function o(a){return void 0===a}function p(a,b){var c,d,e;if(o(b._isAMomentObject)||(a._isAMomentObject=b._isAMomentObject),o(b._i)||(a._i=b._i),o(b._f)||(a._f=b._f),o(b._l)||(a._l=b._l),o(b._strict)||(a._strict=b._strict),o(b._tzm)||(a._tzm=b._tzm),o(b._isUTC)||(a._isUTC=b._isUTC),o(b._offset)||(a._offset=b._offset),o(b._pf)||(a._pf=l(b)),o(b._locale)||(a._locale=b._locale),od.length>0)for(c in od)d=od[c],e=b[d],o(e)||(a[d]=e);return a} +// Moment prototype object +function q(b){p(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),pd===!1&&(pd=!0,a.updateOffset(this),pd=!1)}function r(a){return a instanceof q||null!=a&&null!=a._isAMomentObject}function s(a){return 0>a?Math.ceil(a)||0:Math.floor(a)}function t(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=s(b)),c} +// compare two arrays, return the number of differences +function u(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&t(a[d])!==t(b[d]))&&g++;return g+f}function v(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function w(b,c){var d=!0;return i(function(){return null!=a.deprecationHandler&&a.deprecationHandler(null,b),d&&(v(b+"\nArguments: "+Array.prototype.slice.call(arguments).join(", ")+"\n"+(new Error).stack),d=!1),c.apply(this,arguments)},c)}function x(b,c){null!=a.deprecationHandler&&a.deprecationHandler(b,c),qd[b]||(v(c),qd[b]=!0)}function y(a){return a instanceof Function||"[object Function]"===Object.prototype.toString.call(a)}function z(a){var b,c;for(c in a)b=a[c],y(b)?this[c]=b:this["_"+c]=b;this._config=a, +// Lenient ordinal parsing accepts just a number in addition to +// number + (possibly) stuff coming from _ordinalParseLenient. +this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function A(a,b){var c,e=i({},a);for(c in b)h(b,c)&&(d(a[c])&&d(b[c])?(e[c]={},i(e[c],a[c]),i(e[c],b[c])):null!=b[c]?e[c]=b[c]:delete e[c]);for(c in a)h(a,c)&&!h(b,c)&&d(a[c])&&( +// make sure changes to properties don't modify parent config +e[c]=i({},e[c]));return e}function B(a){null!=a&&this.set(a)}function C(a,b,c){var d=this._calendar[a]||this._calendar.sameElse;return y(d)?d.call(b,c):d}function D(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function E(){return this._invalidDate}function F(a){return this._ordinal.replace("%d",a)}function G(a,b,c,d){var e=this._relativeTime[c];return y(e)?e(a,b,c,d):e.replace(/%d/i,a)}function H(a,b){var c=this._relativeTime[a>0?"future":"past"];return y(c)?c(b):c.replace(/%s/i,b)}function I(a,b){var c=a.toLowerCase();zd[c]=zd[c+"s"]=zd[b]=a}function J(a){return"string"==typeof a?zd[a]||zd[a.toLowerCase()]:void 0}function K(a){var b,c,d={};for(c in a)h(a,c)&&(b=J(c),b&&(d[b]=a[c]));return d}function L(a,b){Ad[a]=b}function M(a){var b=[];for(var c in a)b.push({unit:c,priority:Ad[c]});return b.sort(function(a,b){return a.priority-b.priority}),b}function N(b,c){return function(d){return null!=d?(P(this,b,d),a.updateOffset(this,c),this):O(this,b)}}function O(a,b){return a.isValid()?a._d["get"+(a._isUTC?"UTC":"")+b]():NaN}function P(a,b,c){a.isValid()&&a._d["set"+(a._isUTC?"UTC":"")+b](c)} +// MOMENTS +function Q(a){return a=J(a),y(this[a])?this[a]():this}function R(a,b){if("object"==typeof a){a=K(a);for(var c=M(a),d=0;d<c.length;d++)this[c[d].unit](a[c[d].unit])}else if(a=J(a),y(this[a]))return this[a](b);return this}function S(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d} +// token: 'M' +// padded: ['MM', 2] +// ordinal: 'Mo' +// callback: function () { this.month() + 1 } +function T(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Ed[a]=e),b&&(Ed[b[0]]=function(){return S(e.apply(this,arguments),b[1],b[2])}),c&&(Ed[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function U(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function V(a){var b,c,d=a.match(Bd);for(b=0,c=d.length;c>b;b++)Ed[d[b]]?d[b]=Ed[d[b]]:d[b]=U(d[b]);return function(b){var e,f="";for(e=0;c>e;e++)f+=d[e]instanceof Function?d[e].call(b,a):d[e];return f}} +// format date using native date object +function W(a,b){return a.isValid()?(b=X(b,a.localeData()),Dd[b]=Dd[b]||V(b),Dd[b](a)):a.localeData().invalidDate()}function X(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Cd.lastIndex=0;d>=0&&Cd.test(a);)a=a.replace(Cd,c),Cd.lastIndex=0,d-=1;return a}function Y(a,b,c){Wd[a]=y(b)?b:function(a,d){return a&&c?c:b}}function Z(a,b){return h(Wd,a)?Wd[a](b._strict,b._locale):new RegExp($(a))} +// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript +function $(a){return _(a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}))}function _(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function aa(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=t(a)}),c=0;c<a.length;c++)Xd[a[c]]=d}function ba(a,b){aa(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}function ca(a,b,c){null!=b&&h(Xd,a)&&Xd[a](b,c._a,c,a)}function da(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function ea(a,b){return c(this._months)?this._months[a.month()]:this._months[(this._months.isFormat||fe).test(b)?"format":"standalone"][a.month()]}function fa(a,b){return c(this._monthsShort)?this._monthsShort[a.month()]:this._monthsShort[fe.test(b)?"format":"standalone"][a.month()]}function ga(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._monthsParse)for( +// this is not used +this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],d=0;12>d;++d)f=j([2e3,d]),this._shortMonthsParse[d]=this.monthsShort(f,"").toLocaleLowerCase(),this._longMonthsParse[d]=this.months(f,"").toLocaleLowerCase();return c?"MMM"===b?(e=sd.call(this._shortMonthsParse,g),-1!==e?e:null):(e=sd.call(this._longMonthsParse,g),-1!==e?e:null):"MMM"===b?(e=sd.call(this._shortMonthsParse,g),-1!==e?e:(e=sd.call(this._longMonthsParse,g),-1!==e?e:null)):(e=sd.call(this._longMonthsParse,g),-1!==e?e:(e=sd.call(this._shortMonthsParse,g),-1!==e?e:null))}function ha(a,b,c){var d,e,f;if(this._monthsParseExact)return ga.call(this,a,b,c); +// TODO: add sorting +// Sorting makes sure if one month (or abbr) is a prefix of another +// see sorting in computeMonthsParse +for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;12>d;d++){ +// test the regex +if(e=j([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}} +// MOMENTS +function ia(a,b){var c;if(!a.isValid()) +// No op +return a;if("string"==typeof b)if(/^\d+$/.test(b))b=t(b);else +// TODO: Another silent failure? +if(b=a.localeData().monthsParse(b),"number"!=typeof b)return a;return c=Math.min(a.date(),da(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a}function ja(b){return null!=b?(ia(this,b),a.updateOffset(this,!0),this):O(this,"Month")}function ka(){return da(this.year(),this.month())}function la(a){return this._monthsParseExact?(h(this,"_monthsRegex")||na.call(this),a?this._monthsShortStrictRegex:this._monthsShortRegex):(h(this,"_monthsShortRegex")||(this._monthsShortRegex=ie),this._monthsShortStrictRegex&&a?this._monthsShortStrictRegex:this._monthsShortRegex)}function ma(a){return this._monthsParseExact?(h(this,"_monthsRegex")||na.call(this),a?this._monthsStrictRegex:this._monthsRegex):(h(this,"_monthsRegex")||(this._monthsRegex=je),this._monthsStrictRegex&&a?this._monthsStrictRegex:this._monthsRegex)}function na(){function a(a,b){return b.length-a.length}var b,c,d=[],e=[],f=[];for(b=0;12>b;b++)c=j([2e3,b]),d.push(this.monthsShort(c,"")),e.push(this.months(c,"")),f.push(this.months(c,"")),f.push(this.monthsShort(c,""));for( +// Sorting makes sure if one month (or abbr) is a prefix of another it +// will match the longer piece. +d.sort(a),e.sort(a),f.sort(a),b=0;12>b;b++)d[b]=_(d[b]),e[b]=_(e[b]);for(b=0;24>b;b++)f[b]=_(f[b]);this._monthsRegex=new RegExp("^("+f.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+e.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+d.join("|")+")","i")} +// HELPERS +function oa(a){return pa(a)?366:365}function pa(a){return a%4===0&&a%100!==0||a%400===0}function qa(){return pa(this.year())}function ra(a,b,c,d,e,f,g){ +//can't just apply() to create a date: +//http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply +var h=new Date(a,b,c,d,e,f,g); +//the date constructor remaps years 0-99 to 1900-1999 +return 100>a&&a>=0&&isFinite(h.getFullYear())&&h.setFullYear(a),h}function sa(a){var b=new Date(Date.UTC.apply(null,arguments)); +//the Date.UTC function remaps years 0-99 to 1900-1999 +return 100>a&&a>=0&&isFinite(b.getUTCFullYear())&&b.setUTCFullYear(a),b} +// start-of-first-week - start-of-year +function ta(a,b,c){var// first-week day -- which january is always in the first week (4 for iso, 1 for other) +d=7+b-c, +// first-week day local weekday -- which local weekday is fwd +e=(7+sa(a,0,d).getUTCDay()-b)%7;return-e+d-1} +//http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday +function ua(a,b,c,d,e){var f,g,h=(7+c-d)%7,i=ta(a,d,e),j=1+7*(b-1)+h+i;return 0>=j?(f=a-1,g=oa(f)+j):j>oa(a)?(f=a+1,g=j-oa(a)):(f=a,g=j),{year:f,dayOfYear:g}}function va(a,b,c){var d,e,f=ta(a.year(),b,c),g=Math.floor((a.dayOfYear()-f-1)/7)+1;return 1>g?(e=a.year()-1,d=g+wa(e,b,c)):g>wa(a.year(),b,c)?(d=g-wa(a.year(),b,c),e=a.year()+1):(e=a.year(),d=g),{week:d,year:e}}function wa(a,b,c){var d=ta(a,b,c),e=ta(a+1,b,c);return(oa(a)-d+e)/7} +// HELPERS +// LOCALES +function xa(a){return va(a,this._week.dow,this._week.doy).week}function ya(){return this._week.dow}function za(){return this._week.doy} +// MOMENTS +function Aa(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function Ba(a){var b=va(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")} +// HELPERS +function Ca(a,b){return"string"!=typeof a?a:isNaN(a)?(a=b.weekdaysParse(a),"number"==typeof a?a:null):parseInt(a,10)}function Da(a,b){return"string"==typeof a?b.weekdaysParse(a)%7||7:isNaN(a)?null:a}function Ea(a,b){return c(this._weekdays)?this._weekdays[a.day()]:this._weekdays[this._weekdays.isFormat.test(b)?"format":"standalone"][a.day()]}function Fa(a){return this._weekdaysShort[a.day()]}function Ga(a){return this._weekdaysMin[a.day()]}function Ha(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],d=0;7>d;++d)f=j([2e3,1]).day(d),this._minWeekdaysParse[d]=this.weekdaysMin(f,"").toLocaleLowerCase(),this._shortWeekdaysParse[d]=this.weekdaysShort(f,"").toLocaleLowerCase(),this._weekdaysParse[d]=this.weekdays(f,"").toLocaleLowerCase();return c?"dddd"===b?(e=sd.call(this._weekdaysParse,g),-1!==e?e:null):"ddd"===b?(e=sd.call(this._shortWeekdaysParse,g),-1!==e?e:null):(e=sd.call(this._minWeekdaysParse,g),-1!==e?e:null):"dddd"===b?(e=sd.call(this._weekdaysParse,g),-1!==e?e:(e=sd.call(this._shortWeekdaysParse,g),-1!==e?e:(e=sd.call(this._minWeekdaysParse,g),-1!==e?e:null))):"ddd"===b?(e=sd.call(this._shortWeekdaysParse,g),-1!==e?e:(e=sd.call(this._weekdaysParse,g),-1!==e?e:(e=sd.call(this._minWeekdaysParse,g),-1!==e?e:null))):(e=sd.call(this._minWeekdaysParse,g),-1!==e?e:(e=sd.call(this._weekdaysParse,g),-1!==e?e:(e=sd.call(this._shortWeekdaysParse,g),-1!==e?e:null)))}function Ia(a,b,c){var d,e,f;if(this._weekdaysParseExact)return Ha.call(this,a,b,c);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),d=0;7>d;d++){ +// test the regex +if(e=j([2e3,1]).day(d),c&&!this._fullWeekdaysParse[d]&&(this._fullWeekdaysParse[d]=new RegExp("^"+this.weekdays(e,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[d]=new RegExp("^"+this.weekdaysShort(e,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[d]=new RegExp("^"+this.weekdaysMin(e,"").replace(".",".?")+"$","i")),this._weekdaysParse[d]||(f="^"+this.weekdays(e,"")+"|^"+this.weekdaysShort(e,"")+"|^"+this.weekdaysMin(e,""),this._weekdaysParse[d]=new RegExp(f.replace(".",""),"i")),c&&"dddd"===b&&this._fullWeekdaysParse[d].test(a))return d;if(c&&"ddd"===b&&this._shortWeekdaysParse[d].test(a))return d;if(c&&"dd"===b&&this._minWeekdaysParse[d].test(a))return d;if(!c&&this._weekdaysParse[d].test(a))return d}} +// MOMENTS +function Ja(a){if(!this.isValid())return null!=a?this:NaN;var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Ca(a,this.localeData()),this.add(a-b,"d")):b}function Ka(a){if(!this.isValid())return null!=a?this:NaN;var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function La(a){if(!this.isValid())return null!=a?this:NaN; +// behaves the same as moment#day except +// as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) +// as a setter, sunday should belong to the previous week. +if(null!=a){var b=Da(a,this.localeData());return this.day(this.day()%7?b:b-7)}return this.day()||7}function Ma(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysStrictRegex:this._weekdaysRegex):(h(this,"_weekdaysRegex")||(this._weekdaysRegex=pe),this._weekdaysStrictRegex&&a?this._weekdaysStrictRegex:this._weekdaysRegex)}function Na(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(h(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=qe),this._weekdaysShortStrictRegex&&a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Oa(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(h(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=re),this._weekdaysMinStrictRegex&&a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Pa(){function a(a,b){return b.length-a.length}var b,c,d,e,f,g=[],h=[],i=[],k=[];for(b=0;7>b;b++)c=j([2e3,1]).day(b),d=this.weekdaysMin(c,""),e=this.weekdaysShort(c,""),f=this.weekdays(c,""),g.push(d),h.push(e),i.push(f),k.push(d),k.push(e),k.push(f);for( +// Sorting makes sure if one weekday (or abbr) is a prefix of another it +// will match the longer piece. +g.sort(a),h.sort(a),i.sort(a),k.sort(a),b=0;7>b;b++)h[b]=_(h[b]),i[b]=_(i[b]),k[b]=_(k[b]);this._weekdaysRegex=new RegExp("^("+k.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+h.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+g.join("|")+")","i")} +// FORMATTING +function Qa(){return this.hours()%12||12}function Ra(){return this.hours()||24}function Sa(a,b){T(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})} +// PARSING +function Ta(a,b){return b._meridiemParse} +// LOCALES +function Ua(a){ +// IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays +// Using charAt should be more compatible. +return"p"===(a+"").toLowerCase().charAt(0)}function Va(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Wa(a){return a?a.toLowerCase().replace("_","-"):a} +// pick the locale from the array +// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each +// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root +function Xa(a){for(var b,c,d,e,f=0;f<a.length;){for(e=Wa(a[f]).split("-"),b=e.length,c=Wa(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=Ya(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&u(e,c,!0)>=b-1) +//the next array item is better than a shallower substring of this one +break;b--}f++}return null}function Ya(a){var b=null; +// TODO: Find a better way to register and load all the locales in Node +if(!we[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=se._abbr,require("./locale/"+a), +// because defineLocale currently also sets the global locale, we +// want to undo that for lazy loaded locales +Za(b)}catch(c){}return we[a]} +// This function will load locale and then set the global locale. If +// no arguments are passed in, it will simply return the current global +// locale key. +function Za(a,b){var c; +// moment.duration._locale = moment._locale = data; +return a&&(c=o(b)?ab(a):$a(a,b),c&&(se=c)),se._abbr}function $a(a,b){if(null!==b){var c=ve; +// treat as if there is no base config +// backwards compat for now: also set the locale +return b.abbr=a,null!=we[a]?(x("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),c=we[a]._config):null!=b.parentLocale&&(null!=we[b.parentLocale]?c=we[b.parentLocale]._config:x("parentLocaleUndefined","specified parentLocale is not defined yet. See http://momentjs.com/guides/#/warnings/parent-locale/")),we[a]=new B(A(c,b)),Za(a),we[a]} +// useful for testing +return delete we[a],null}function _a(a,b){if(null!=b){var c,d=ve; +// MERGE +null!=we[a]&&(d=we[a]._config),b=A(d,b),c=new B(b),c.parentLocale=we[a],we[a]=c, +// backwards compat for now: also set the locale +Za(a)}else +// pass null for config to unupdate, useful for tests +null!=we[a]&&(null!=we[a].parentLocale?we[a]=we[a].parentLocale:null!=we[a]&&delete we[a]);return we[a]} +// returns locale data +function ab(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return se;if(!c(a)){if(b=Ya(a))return b;a=[a]}return Xa(a)}function bb(){return rd(we)}function cb(a){var b,c=a._a;return c&&-2===l(a).overflow&&(b=c[Zd]<0||c[Zd]>11?Zd:c[$d]<1||c[$d]>da(c[Yd],c[Zd])?$d:c[_d]<0||c[_d]>24||24===c[_d]&&(0!==c[ae]||0!==c[be]||0!==c[ce])?_d:c[ae]<0||c[ae]>59?ae:c[be]<0||c[be]>59?be:c[ce]<0||c[ce]>999?ce:-1,l(a)._overflowDayOfYear&&(Yd>b||b>$d)&&(b=$d),l(a)._overflowWeeks&&-1===b&&(b=de),l(a)._overflowWeekday&&-1===b&&(b=ee),l(a).overflow=b),a} +// date from iso format +function db(a){var b,c,d,e,f,g,h=a._i,i=xe.exec(h)||ye.exec(h);if(i){for(l(a).iso=!0,b=0,c=Ae.length;c>b;b++)if(Ae[b][1].exec(i[1])){e=Ae[b][0],d=Ae[b][2]!==!1;break}if(null==e)return void(a._isValid=!1);if(i[3]){for(b=0,c=Be.length;c>b;b++)if(Be[b][1].exec(i[3])){ +// match[2] should be 'T' or space +f=(i[2]||" ")+Be[b][0];break}if(null==f)return void(a._isValid=!1)}if(!d&&null!=f)return void(a._isValid=!1);if(i[4]){if(!ze.exec(i[4]))return void(a._isValid=!1);g="Z"}a._f=e+(f||"")+(g||""),jb(a)}else a._isValid=!1} +// date from iso format or fallback +function eb(b){var c=Ce.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(db(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))} +// Pick the first defined of two or three arguments. +function fb(a,b,c){return null!=a?a:null!=b?b:c}function gb(b){ +// hooks is actually the exported moment object +var c=new Date(a.now());return b._useUTC?[c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate()]:[c.getFullYear(),c.getMonth(),c.getDate()]} +// convert an array to a date. +// the array should mirror the parameters below +// note: all values past the year are optional and will default to the lowest possible value. +// [year, month, day , hour, minute, second, millisecond] +function hb(a){var b,c,d,e,f=[];if(!a._d){ +// Default to current date. +// * if no year, month, day of month are given, default to today +// * if day of month is given, default month and year +// * if month is given, default only year +// * if year is given, don't default anything +for(d=gb(a),a._w&&null==a._a[$d]&&null==a._a[Zd]&&ib(a),a._dayOfYear&&(e=fb(a._a[Yd],d[Yd]),a._dayOfYear>oa(e)&&(l(a)._overflowDayOfYear=!0),c=sa(e,0,a._dayOfYear),a._a[Zd]=c.getUTCMonth(),a._a[$d]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b]; +// Zero out whatever was not defaulted, including time +for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b]; +// Check for 24:00:00.000 +24===a._a[_d]&&0===a._a[ae]&&0===a._a[be]&&0===a._a[ce]&&(a._nextDay=!0,a._a[_d]=0),a._d=(a._useUTC?sa:ra).apply(null,f), +// Apply timezone offset from input. The actual utcOffset can be changed +// with parseZone. +null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[_d]=24)}}function ib(a){var b,c,d,e,f,g,h,i;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=fb(b.GG,a._a[Yd],va(rb(),1,4).year),d=fb(b.W,1),e=fb(b.E,1),(1>e||e>7)&&(i=!0)):(f=a._locale._week.dow,g=a._locale._week.doy,c=fb(b.gg,a._a[Yd],va(rb(),f,g).year),d=fb(b.w,1),null!=b.d?(e=b.d,(0>e||e>6)&&(i=!0)):null!=b.e?(e=b.e+f,(b.e<0||b.e>6)&&(i=!0)):e=f),1>d||d>wa(c,f,g)?l(a)._overflowWeeks=!0:null!=i?l(a)._overflowWeekday=!0:(h=ua(c,d,e,f,g),a._a[Yd]=h.year,a._dayOfYear=h.dayOfYear)} +// date from string and format string +function jb(b){ +// TODO: Move this to another part of the creation flow to prevent circular deps +if(b._f===a.ISO_8601)return void db(b);b._a=[],l(b).empty=!0; +// This array is used to make a Date, either with `new Date` or `Date.UTC` +var c,d,e,f,g,h=""+b._i,i=h.length,j=0;for(e=X(b._f,b._locale).match(Bd)||[],c=0;c<e.length;c++)f=e[c],d=(h.match(Z(f,b))||[])[0],d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&l(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),j+=d.length),Ed[f]?(d?l(b).empty=!1:l(b).unusedTokens.push(f),ca(f,d,b)):b._strict&&!d&&l(b).unusedTokens.push(f); +// add remaining unparsed input length to the string +l(b).charsLeftOver=i-j,h.length>0&&l(b).unusedInput.push(h), +// clear _12h flag if hour is <= 12 +b._a[_d]<=12&&l(b).bigHour===!0&&b._a[_d]>0&&(l(b).bigHour=void 0),l(b).parsedDateParts=b._a.slice(0),l(b).meridiem=b._meridiem, +// handle meridiem +b._a[_d]=kb(b._locale,b._a[_d],b._meridiem),hb(b),cb(b)}function kb(a,b,c){var d; +// Fallback +return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b} +// date from string and array of format strings +function lb(a){var b,c,d,e,f;if(0===a._f.length)return l(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;e<a._f.length;e++)f=0,b=p({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._f=a._f[e],jb(b),m(b)&&(f+=l(b).charsLeftOver,f+=10*l(b).unusedTokens.length,l(b).score=f,(null==d||d>f)&&(d=f,c=b));i(a,c||b)}function mb(a){if(!a._d){var b=K(a._i);a._a=g([b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],function(a){return a&&parseInt(a,10)}),hb(a)}}function nb(a){var b=new q(cb(ob(a))); +// Adding is smart enough around DST +return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function ob(a){var b=a._i,d=a._f;return a._locale=a._locale||ab(a._l),null===b||void 0===d&&""===b?n({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),r(b)?new q(cb(b)):(c(d)?lb(a):f(b)?a._d=b:d?jb(a):pb(a),m(a)||(a._d=null),a))}function pb(b){var d=b._i;void 0===d?b._d=new Date(a.now()):f(d)?b._d=new Date(d.valueOf()):"string"==typeof d?eb(b):c(d)?(b._a=g(d.slice(0),function(a){return parseInt(a,10)}),hb(b)):"object"==typeof d?mb(b):"number"==typeof d? +// from milliseconds +b._d=new Date(d):a.createFromInputFallback(b)}function qb(a,b,f,g,h){var i={}; +// object construction must be done this way. +// https://github.com/moment/moment/issues/1423 +return"boolean"==typeof f&&(g=f,f=void 0),(d(a)&&e(a)||c(a)&&0===a.length)&&(a=void 0),i._isAMomentObject=!0,i._useUTC=i._isUTC=h,i._l=f,i._i=a,i._f=b,i._strict=g,nb(i)}function rb(a,b,c,d){return qb(a,b,c,d,!1)} +// Pick a moment m from moments so that m[fn](other) is true for all +// other. This relies on the function fn to be transitive. +// +// moments should either be an array of moment objects or an array, whose +// first element is an array of moment objects. +function sb(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return rb();for(d=b[0],e=1;e<b.length;++e)b[e].isValid()&&!b[e][a](d)||(d=b[e]);return d} +// TODO: Use [].sort instead? +function tb(){var a=[].slice.call(arguments,0);return sb("isBefore",a)}function ub(){var a=[].slice.call(arguments,0);return sb("isAfter",a)}function vb(a){var b=K(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0; +// representation for dateAddRemove +this._milliseconds=+k+1e3*j+// 1000 +6e4*i+// 1000 * 60 +1e3*h*60*60,//using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978 +// Because of dateAddRemove treats 24 hours as different from a +// day when working around DST, we need to store them separately +this._days=+g+7*f, +// It is impossible translate months into days without knowing +// which months you are are talking about, so we have to store +// it separately. +this._months=+e+3*d+12*c,this._data={},this._locale=ab(),this._bubble()}function wb(a){return a instanceof vb} +// FORMATTING +function xb(a,b){T(a,0,0,function(){var a=this.utcOffset(),c="+";return 0>a&&(a=-a,c="-"),c+S(~~(a/60),2)+b+S(~~a%60,2)})}function yb(a,b){var c=(b||"").match(a)||[],d=c[c.length-1]||[],e=(d+"").match(Ge)||["-",0,0],f=+(60*e[1])+t(e[2]);return"+"===e[0]?f:-f} +// Return a moment from input, that is local/utc/zone equivalent to model. +function zb(b,c){var d,e; +// Use low-level api, because this fn is low-level api. +return c._isUTC?(d=c.clone(),e=(r(b)||f(b)?b.valueOf():rb(b).valueOf())-d.valueOf(),d._d.setTime(d._d.valueOf()+e),a.updateOffset(d,!1),d):rb(b).local()}function Ab(a){ +// On Firefox.24 Date#getTimezoneOffset returns a floating point. +// https://github.com/moment/moment/pull/1871 +return 15*-Math.round(a._d.getTimezoneOffset()/15)} +// MOMENTS +// keepLocalTime = true means only change the timezone, without +// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> +// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset +// +0200, so we adjust the time as needed, to be valid. +// +// Keeping the time actually adds/subtracts (one hour) +// from the actual represented time. That is why we call updateOffset +// a second time. In case it wants us to change the offset again +// _changeInProgress == true case, then we have to adjust, because +// there is no such time in the given timezone. +function Bb(b,c){var d,e=this._offset||0;return this.isValid()?null!=b?("string"==typeof b?b=yb(Td,b):Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ab(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?Sb(this,Mb(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ab(this):null!=b?this:NaN}function Cb(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Db(a){return this.utcOffset(0,a)}function Eb(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ab(this),"m")),this}function Fb(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(yb(Sd,this._i)),this}function Gb(a){return this.isValid()?(a=a?rb(a).utcOffset():0,(this.utcOffset()-a)%60===0):!1}function Hb(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ib(){if(!o(this._isDSTShifted))return this._isDSTShifted;var a={};if(p(a,this),a=ob(a),a._a){var b=a._isUTC?j(a._a):rb(a._a);this._isDSTShifted=this.isValid()&&u(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Jb(){return this.isValid()?!this._isUTC:!1}function Kb(){return this.isValid()?this._isUTC:!1}function Lb(){return this.isValid()?this._isUTC&&0===this._offset:!1}function Mb(a,b){var c,d,e,f=a, +// matching against regexp is expensive, do it on demand +g=null;// checks for null or undefined +return wb(a)?f={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(f={},b?f[b]=a:f.milliseconds=a):(g=He.exec(a))?(c="-"===g[1]?-1:1,f={y:0,d:t(g[$d])*c,h:t(g[_d])*c,m:t(g[ae])*c,s:t(g[be])*c,ms:t(g[ce])*c}):(g=Ie.exec(a))?(c="-"===g[1]?-1:1,f={y:Nb(g[2],c),M:Nb(g[3],c),w:Nb(g[4],c),d:Nb(g[5],c),h:Nb(g[6],c),m:Nb(g[7],c),s:Nb(g[8],c)}):null==f?f={}:"object"==typeof f&&("from"in f||"to"in f)&&(e=Pb(rb(f.from),rb(f.to)),f={},f.ms=e.milliseconds,f.M=e.months),d=new vb(f),wb(a)&&h(a,"_locale")&&(d._locale=a._locale),d}function Nb(a,b){ +// We'd normally use ~~inp for this, but unfortunately it also +// converts floats to ints. +// inp may be undefined, so careful calling replace on it. +var c=a&&parseFloat(a.replace(",",".")); +// apply sign while we're at it +return(isNaN(c)?0:c)*b}function Ob(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function Pb(a,b){var c;return a.isValid()&&b.isValid()?(b=zb(b,a),a.isBefore(b)?c=Ob(a,b):(c=Ob(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c):{milliseconds:0,months:0}}function Qb(a){return 0>a?-1*Math.round(-1*a):Math.round(a)} +// TODO: remove 'name' arg after deprecation is removed +function Rb(a,b){return function(c,d){var e,f; +//invert the arguments, but complain about it +return null===d||isNaN(+d)||(x(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Mb(c,d),Sb(this,e,a),this}}function Sb(b,c,d,e){var f=c._milliseconds,g=Qb(c._days),h=Qb(c._months);b.isValid()&&(e=null==e?!0:e,f&&b._d.setTime(b._d.valueOf()+f*d),g&&P(b,"Date",O(b,"Date")+g*d),h&&ia(b,O(b,"Month")+h*d),e&&a.updateOffset(b,g||h))}function Tb(a,b){var c=a.diff(b,"days",!0);return-6>c?"sameElse":-1>c?"lastWeek":0>c?"lastDay":1>c?"sameDay":2>c?"nextDay":7>c?"nextWeek":"sameElse"}function Ub(b,c){ +// We want to compare the start of today, vs this. +// Getting start-of-today depends on whether we're local/utc/offset or not. +var d=b||rb(),e=zb(d,this).startOf("day"),f=a.calendarFormat(this,e)||"sameElse",g=c&&(y(c[f])?c[f].call(this,d):c[f]);return this.format(g||this.localeData().calendar(f,this,rb(d)))}function Vb(){return new q(this)}function Wb(a,b){var c=r(a)?a:rb(a);return this.isValid()&&c.isValid()?(b=J(o(b)?"millisecond":b),"millisecond"===b?this.valueOf()>c.valueOf():c.valueOf()<this.clone().startOf(b).valueOf()):!1}function Xb(a,b){var c=r(a)?a:rb(a);return this.isValid()&&c.isValid()?(b=J(o(b)?"millisecond":b),"millisecond"===b?this.valueOf()<c.valueOf():this.clone().endOf(b).valueOf()<c.valueOf()):!1}function Yb(a,b,c,d){return d=d||"()",("("===d[0]?this.isAfter(a,c):!this.isBefore(a,c))&&(")"===d[1]?this.isBefore(b,c):!this.isAfter(b,c))}function Zb(a,b){var c,d=r(a)?a:rb(a);return this.isValid()&&d.isValid()?(b=J(b||"millisecond"),"millisecond"===b?this.valueOf()===d.valueOf():(c=d.valueOf(),this.clone().startOf(b).valueOf()<=c&&c<=this.clone().endOf(b).valueOf())):!1}function $b(a,b){return this.isSame(a,b)||this.isAfter(a,b)}function _b(a,b){return this.isSame(a,b)||this.isBefore(a,b)}function ac(a,b,c){var d,e,f,g;// 1000 +// 1000 * 60 +// 1000 * 60 * 60 +// 1000 * 60 * 60 * 24, negate dst +// 1000 * 60 * 60 * 24 * 7, negate dst +return this.isValid()?(d=zb(a,this),d.isValid()?(e=6e4*(d.utcOffset()-this.utcOffset()),b=J(b),"year"===b||"month"===b||"quarter"===b?(g=bc(this,d),"quarter"===b?g/=3:"year"===b&&(g/=12)):(f=this-d,g="second"===b?f/1e3:"minute"===b?f/6e4:"hour"===b?f/36e5:"day"===b?(f-e)/864e5:"week"===b?(f-e)/6048e5:f),c?g:s(g)):NaN):NaN}function bc(a,b){ +// difference in months +var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()), +// b is in (anchor - 1 month, anchor + 1 month) +f=a.clone().add(e,"months"); +//check for negative zero, return zero if negative zero +// linear across the month +// linear across the month +return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)||0}function cc(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function dc(){var a=this.clone().utc();return 0<a.year()&&a.year()<=9999?y(Date.prototype.toISOString)?this.toDate().toISOString():W(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):W(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function ec(b){b||(b=this.isUtc()?a.defaultFormatUtc:a.defaultFormat);var c=W(this,b);return this.localeData().postformat(c)}function fc(a,b){return this.isValid()&&(r(a)&&a.isValid()||rb(a).isValid())?Mb({to:this,from:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function gc(a){return this.from(rb(),a)}function hc(a,b){return this.isValid()&&(r(a)&&a.isValid()||rb(a).isValid())?Mb({from:this,to:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function ic(a){return this.to(rb(),a)} +// If passed a locale key, it will set the locale for this +// instance. Otherwise, it will return the locale configuration +// variables for this instance. +function jc(a){var b;return void 0===a?this._locale._abbr:(b=ab(a),null!=b&&(this._locale=b),this)}function kc(){return this._locale}function lc(a){ +// the following switch intentionally omits break keywords +// to utilize falling through the cases. +switch(a=J(a)){case"year":this.month(0);/* falls through */ +case"quarter":case"month":this.date(1);/* falls through */ +case"week":case"isoWeek":case"day":case"date":this.hours(0);/* falls through */ +case"hour":this.minutes(0);/* falls through */ +case"minute":this.seconds(0);/* falls through */ +case"second":this.milliseconds(0)} +// weeks are a special case +// quarters are also special +return"week"===a&&this.weekday(0),"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this}function mc(a){ +// 'date' is an alias for 'day', so it should be considered as such. +return a=J(a),void 0===a||"millisecond"===a?this:("date"===a&&(a="day"),this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms"))}function nc(){return this._d.valueOf()-6e4*(this._offset||0)}function oc(){return Math.floor(this.valueOf()/1e3)}function pc(){return new Date(this.valueOf())}function qc(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.minute(),a.second(),a.millisecond()]}function rc(){var a=this;return{years:a.year(),months:a.month(),date:a.date(),hours:a.hours(),minutes:a.minutes(),seconds:a.seconds(),milliseconds:a.milliseconds()}}function sc(){ +// new Date(NaN).toJSON() === null +return this.isValid()?this.toISOString():null}function tc(){return m(this)}function uc(){return i({},l(this))}function vc(){return l(this).overflow}function wc(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function xc(a,b){T(0,[a,a.length],0,b)} +// MOMENTS +function yc(a){return Cc.call(this,a,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function zc(a){return Cc.call(this,a,this.isoWeek(),this.isoWeekday(),1,4)}function Ac(){return wa(this.year(),1,4)}function Bc(){var a=this.localeData()._week;return wa(this.year(),a.dow,a.doy)}function Cc(a,b,c,d,e){var f;return null==a?va(this,d,e).year:(f=wa(a,d,e),b>f&&(b=f),Dc.call(this,a,b,c,d,e))}function Dc(a,b,c,d,e){var f=ua(a,b,c,d,e),g=sa(f.year,0,f.dayOfYear);return this.year(g.getUTCFullYear()),this.month(g.getUTCMonth()),this.date(g.getUTCDate()),this} +// MOMENTS +function Ec(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)} +// HELPERS +// MOMENTS +function Fc(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function Gc(a,b){b[ce]=t(1e3*("0."+a))} +// MOMENTS +function Hc(){return this._isUTC?"UTC":""}function Ic(){return this._isUTC?"Coordinated Universal Time":""}function Jc(a){return rb(1e3*a)}function Kc(){return rb.apply(null,arguments).parseZone()}function Lc(a){return a}function Mc(a,b,c,d){var e=ab(),f=j().set(d,b);return e[c](f,a)}function Nc(a,b,c){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return Mc(a,b,c,"month");var d,e=[];for(d=0;12>d;d++)e[d]=Mc(a,d,c,"month");return e} +// () +// (5) +// (fmt, 5) +// (fmt) +// (true) +// (true, 5) +// (true, fmt, 5) +// (true, fmt) +function Oc(a,b,c,d){"boolean"==typeof a?("number"==typeof b&&(c=b,b=void 0),b=b||""):(b=a,c=b,a=!1,"number"==typeof b&&(c=b,b=void 0),b=b||"");var e=ab(),f=a?e._week.dow:0;if(null!=c)return Mc(b,(c+f)%7,d,"day");var g,h=[];for(g=0;7>g;g++)h[g]=Mc(b,(g+f)%7,d,"day");return h}function Pc(a,b){return Nc(a,b,"months")}function Qc(a,b){return Nc(a,b,"monthsShort")}function Rc(a,b,c){return Oc(a,b,c,"weekdays")}function Sc(a,b,c){return Oc(a,b,c,"weekdaysShort")}function Tc(a,b,c){return Oc(a,b,c,"weekdaysMin")}function Uc(){var a=this._data;return this._milliseconds=Ue(this._milliseconds),this._days=Ue(this._days),this._months=Ue(this._months),a.milliseconds=Ue(a.milliseconds),a.seconds=Ue(a.seconds),a.minutes=Ue(a.minutes),a.hours=Ue(a.hours),a.months=Ue(a.months),a.years=Ue(a.years),this}function Vc(a,b,c,d){var e=Mb(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()} +// supports only 2.0-style add(1, 's') or add(duration) +function Wc(a,b){return Vc(this,a,b,1)} +// supports only 2.0-style subtract(1, 's') or subtract(duration) +function Xc(a,b){return Vc(this,a,b,-1)}function Yc(a){return 0>a?Math.floor(a):Math.ceil(a)}function Zc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data; +// if we have a mix of positive and negative values, bubble down first +// check: https://github.com/moment/moment/issues/2166 +// The following code bubbles up values, see the tests for +// examples of what that means. +// convert days to months +// 12 months -> 1 year +return f>=0&&g>=0&&h>=0||0>=f&&0>=g&&0>=h||(f+=864e5*Yc(_c(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=s(f/1e3),i.seconds=a%60,b=s(a/60),i.minutes=b%60,c=s(b/60),i.hours=c%24,g+=s(c/24),e=s($c(g)),h+=e,g-=Yc(_c(e)),d=s(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function $c(a){ +// 400 years have 146097 days (taking into account leap year rules) +// 400 years have 12 months === 4800 +return 4800*a/146097}function _c(a){ +// the reverse of daysToMonths +return 146097*a/4800}function ad(a){var b,c,d=this._milliseconds;if(a=J(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+$c(b),"month"===a?c:c/12;switch(b=this._days+Math.round(_c(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3; +// Math.floor prevents floating point math errors here +case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}} +// TODO: Use this.as('ms')? +function bd(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*t(this._months/12)}function cd(a){return function(){return this.as(a)}}function dd(a){return a=J(a),this[a+"s"]()}function ed(a){return function(){return this._data[a]}}function fd(){return s(this.days()/7)} +// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize +function gd(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function hd(a,b,c){var d=Mb(a).abs(),e=jf(d.as("s")),f=jf(d.as("m")),g=jf(d.as("h")),h=jf(d.as("d")),i=jf(d.as("M")),j=jf(d.as("y")),k=e<kf.s&&["s",e]||1>=f&&["m"]||f<kf.m&&["mm",f]||1>=g&&["h"]||g<kf.h&&["hh",g]||1>=h&&["d"]||h<kf.d&&["dd",h]||1>=i&&["M"]||i<kf.M&&["MM",i]||1>=j&&["y"]||["yy",j];return k[2]=b,k[3]=+a>0,k[4]=c,gd.apply(null,k)} +// This function allows you to set the rounding function for relative time strings +function id(a){return void 0===a?jf:"function"==typeof a?(jf=a,!0):!1} +// This function allows you to set a threshold for relative time strings +function jd(a,b){return void 0===kf[a]?!1:void 0===b?kf[a]:(kf[a]=b,!0)}function kd(a){var b=this.localeData(),c=hd(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function ld(){ +// for ISO strings we do not use the normal bubbling rules: +// * milliseconds bubble up until they become hours +// * days do not bubble at all +// * months bubble up until they become years +// This is because there is no context-free conversion between hours and days +// (think of clock changes) +// and also not between days and months (28-31 days per month) +var a,b,c,d=lf(this._milliseconds)/1e3,e=lf(this._days),f=lf(this._months);a=s(d/60),b=s(a/60),d%=60,a%=60,c=s(f/12),f%=12; +// inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js +var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(0>m?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var md,nd;nd=Array.prototype.some?Array.prototype.some:function(a){for(var b=Object(this),c=b.length>>>0,d=0;c>d;d++)if(d in b&&a.call(this,b[d],d,b))return!0;return!1}; +// Plugins that add properties should also add the key here (null value), +// so we can properly clone ourselves. +var od=a.momentProperties=[],pd=!1,qd={};a.suppressDeprecationWarnings=!1,a.deprecationHandler=null;var rd;rd=Object.keys?Object.keys:function(a){var b,c=[];for(b in a)h(a,b)&&c.push(b);return c};var sd,td={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},ud={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},vd="Invalid date",wd="%d",xd=/\d{1,2}/,yd={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},zd={},Ad={},Bd=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,Cd=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Dd={},Ed={},Fd=/\d/,Gd=/\d\d/,Hd=/\d{3}/,Id=/\d{4}/,Jd=/[+-]?\d{6}/,Kd=/\d\d?/,Ld=/\d\d\d\d?/,Md=/\d\d\d\d\d\d?/,Nd=/\d{1,3}/,Od=/\d{1,4}/,Pd=/[+-]?\d{1,6}/,Qd=/\d+/,Rd=/[+-]?\d+/,Sd=/Z|[+-]\d\d:?\d\d/gi,Td=/Z|[+-]\d\d(?::?\d\d)?/gi,Ud=/[+-]?\d+(\.\d{1,3})?/,Vd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Wd={},Xd={},Yd=0,Zd=1,$d=2,_d=3,ae=4,be=5,ce=6,de=7,ee=8;sd=Array.prototype.indexOf?Array.prototype.indexOf:function(a){ +// I know +var b;for(b=0;b<this.length;++b)if(this[b]===a)return b;return-1},T("M",["MM",2],"Mo",function(){return this.month()+1}),T("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),T("MMMM",0,0,function(a){return this.localeData().months(this,a)}),I("month","M"),L("month",8),Y("M",Kd),Y("MM",Kd,Gd),Y("MMM",function(a,b){return b.monthsShortRegex(a)}),Y("MMMM",function(a,b){return b.monthsRegex(a)}),aa(["M","MM"],function(a,b){b[Zd]=t(a)-1}),aa(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[Zd]=e:l(c).invalidMonth=a}); +// LOCALES +var fe=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/,ge="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),he="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),ie=Vd,je=Vd; +// FORMATTING +T("Y",0,0,function(){var a=this.year();return 9999>=a?""+a:"+"+a}),T(0,["YY",2],0,function(){return this.year()%100}),T(0,["YYYY",4],0,"year"),T(0,["YYYYY",5],0,"year"),T(0,["YYYYYY",6,!0],0,"year"), +// ALIASES +I("year","y"), +// PRIORITIES +L("year",1), +// PARSING +Y("Y",Rd),Y("YY",Kd,Gd),Y("YYYY",Od,Id),Y("YYYYY",Pd,Jd),Y("YYYYYY",Pd,Jd),aa(["YYYYY","YYYYYY"],Yd),aa("YYYY",function(b,c){c[Yd]=2===b.length?a.parseTwoDigitYear(b):t(b)}),aa("YY",function(b,c){c[Yd]=a.parseTwoDigitYear(b)}),aa("Y",function(a,b){b[Yd]=parseInt(a,10)}), +// HOOKS +a.parseTwoDigitYear=function(a){return t(a)+(t(a)>68?1900:2e3)}; +// MOMENTS +var ke=N("FullYear",!0); +// FORMATTING +T("w",["ww",2],"wo","week"),T("W",["WW",2],"Wo","isoWeek"), +// ALIASES +I("week","w"),I("isoWeek","W"), +// PRIORITIES +L("week",5),L("isoWeek",5), +// PARSING +Y("w",Kd),Y("ww",Kd,Gd),Y("W",Kd),Y("WW",Kd,Gd),ba(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=t(a)});var le={dow:0,// Sunday is the first day of the week. +doy:6}; +// FORMATTING +T("d",0,"do","day"),T("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),T("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),T("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),T("e",0,0,"weekday"),T("E",0,0,"isoWeekday"), +// ALIASES +I("day","d"),I("weekday","e"),I("isoWeekday","E"), +// PRIORITY +L("day",11),L("weekday",11),L("isoWeekday",11), +// PARSING +Y("d",Kd),Y("e",Kd),Y("E",Kd),Y("dd",function(a,b){return b.weekdaysMinRegex(a)}),Y("ddd",function(a,b){return b.weekdaysShortRegex(a)}),Y("dddd",function(a,b){return b.weekdaysRegex(a)}),ba(["dd","ddd","dddd"],function(a,b,c,d){var e=c._locale.weekdaysParse(a,d,c._strict); +// if we didn't get a weekday name, mark the date as invalid +null!=e?b.d=e:l(c).invalidWeekday=a}),ba(["d","e","E"],function(a,b,c,d){b[d]=t(a)}); +// LOCALES +var me="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),ne="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),oe="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),pe=Vd,qe=Vd,re=Vd;T("H",["HH",2],0,"hour"),T("h",["hh",2],0,Qa),T("k",["kk",2],0,Ra),T("hmm",0,0,function(){return""+Qa.apply(this)+S(this.minutes(),2)}),T("hmmss",0,0,function(){return""+Qa.apply(this)+S(this.minutes(),2)+S(this.seconds(),2)}),T("Hmm",0,0,function(){return""+this.hours()+S(this.minutes(),2)}),T("Hmmss",0,0,function(){return""+this.hours()+S(this.minutes(),2)+S(this.seconds(),2)}),Sa("a",!0),Sa("A",!1), +// ALIASES +I("hour","h"), +// PRIORITY +L("hour",13),Y("a",Ta),Y("A",Ta),Y("H",Kd),Y("h",Kd),Y("HH",Kd,Gd),Y("hh",Kd,Gd),Y("hmm",Ld),Y("hmmss",Md),Y("Hmm",Ld),Y("Hmmss",Md),aa(["H","HH"],_d),aa(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),aa(["h","hh"],function(a,b,c){b[_d]=t(a),l(c).bigHour=!0}),aa("hmm",function(a,b,c){var d=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d)),l(c).bigHour=!0}),aa("hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d,2)),b[be]=t(a.substr(e)),l(c).bigHour=!0}),aa("Hmm",function(a,b,c){var d=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d))}),aa("Hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d,2)),b[be]=t(a.substr(e))});var se,te=/[ap]\.?m?\.?/i,ue=N("Hours",!0),ve={calendar:td,longDateFormat:ud,invalidDate:vd,ordinal:wd,ordinalParse:xd,relativeTime:yd,months:ge,monthsShort:he,week:le,weekdays:me,weekdaysMin:oe,weekdaysShort:ne,meridiemParse:te},we={},xe=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,ye=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,ze=/Z|[+-]\d\d(?::?\d\d)?/,Ae=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/], +// YYYYMM is NOT allowed by the standard +["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Be=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Ce=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=w("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}), +// constant that refers to the ISO standard +a.ISO_8601=function(){};var De=w("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var a=rb.apply(null,arguments);return this.isValid()&&a.isValid()?this>a?this:a:n()}),Ee=w("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var a=rb.apply(null,arguments);return this.isValid()&&a.isValid()?a>this?this:a:n()}),Fe=function(){return Date.now?Date.now():+new Date};xb("Z",":"),xb("ZZ",""), +// PARSING +Y("Z",Td),Y("ZZ",Td),aa(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=yb(Td,a)}); +// HELPERS +// timezone chunker +// '+10:00' > ['10', '00'] +// '-1530' > ['-15', '30'] +var Ge=/([\+\-]|\d\d)/gi; +// HOOKS +// This function will be called whenever a moment is mutated. +// It is intended to keep the offset in sync with the timezone. +a.updateOffset=function(){}; +// ASP.NET json date format regex +var He=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/,Ie=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;Mb.fn=vb.prototype;var Je=Rb(1,"add"),Ke=Rb(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",a.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Le=w("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)}); +// FORMATTING +T(0,["gg",2],0,function(){return this.weekYear()%100}),T(0,["GG",2],0,function(){return this.isoWeekYear()%100}),xc("gggg","weekYear"),xc("ggggg","weekYear"),xc("GGGG","isoWeekYear"),xc("GGGGG","isoWeekYear"), +// ALIASES +I("weekYear","gg"),I("isoWeekYear","GG"), +// PRIORITY +L("weekYear",1),L("isoWeekYear",1), +// PARSING +Y("G",Rd),Y("g",Rd),Y("GG",Kd,Gd),Y("gg",Kd,Gd),Y("GGGG",Od,Id),Y("gggg",Od,Id),Y("GGGGG",Pd,Jd),Y("ggggg",Pd,Jd),ba(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=t(a)}),ba(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}), +// FORMATTING +T("Q",0,"Qo","quarter"), +// ALIASES +I("quarter","Q"), +// PRIORITY +L("quarter",7), +// PARSING +Y("Q",Fd),aa("Q",function(a,b){b[Zd]=3*(t(a)-1)}), +// FORMATTING +T("D",["DD",2],"Do","date"), +// ALIASES +I("date","D"), +// PRIOROITY +L("date",9), +// PARSING +Y("D",Kd),Y("DD",Kd,Gd),Y("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),aa(["D","DD"],$d),aa("Do",function(a,b){b[$d]=t(a.match(Kd)[0],10)}); +// MOMENTS +var Me=N("Date",!0); +// FORMATTING +T("DDD",["DDDD",3],"DDDo","dayOfYear"), +// ALIASES +I("dayOfYear","DDD"), +// PRIORITY +L("dayOfYear",4), +// PARSING +Y("DDD",Nd),Y("DDDD",Hd),aa(["DDD","DDDD"],function(a,b,c){c._dayOfYear=t(a)}), +// FORMATTING +T("m",["mm",2],0,"minute"), +// ALIASES +I("minute","m"), +// PRIORITY +L("minute",14), +// PARSING +Y("m",Kd),Y("mm",Kd,Gd),aa(["m","mm"],ae); +// MOMENTS +var Ne=N("Minutes",!1); +// FORMATTING +T("s",["ss",2],0,"second"), +// ALIASES +I("second","s"), +// PRIORITY +L("second",15), +// PARSING +Y("s",Kd),Y("ss",Kd,Gd),aa(["s","ss"],be); +// MOMENTS +var Oe=N("Seconds",!1); +// FORMATTING +T("S",0,0,function(){return~~(this.millisecond()/100)}),T(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),T(0,["SSS",3],0,"millisecond"),T(0,["SSSS",4],0,function(){return 10*this.millisecond()}),T(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),T(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),T(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),T(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),T(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}), +// ALIASES +I("millisecond","ms"), +// PRIORITY +L("millisecond",16), +// PARSING +Y("S",Nd,Fd),Y("SS",Nd,Gd),Y("SSS",Nd,Hd);var Pe;for(Pe="SSSS";Pe.length<=9;Pe+="S")Y(Pe,Qd);for(Pe="S";Pe.length<=9;Pe+="S")aa(Pe,Gc); +// MOMENTS +var Qe=N("Milliseconds",!1); +// FORMATTING +T("z",0,0,"zoneAbbr"),T("zz",0,0,"zoneName");var Re=q.prototype;Re.add=Je,Re.calendar=Ub,Re.clone=Vb,Re.diff=ac,Re.endOf=mc,Re.format=ec,Re.from=fc,Re.fromNow=gc,Re.to=hc,Re.toNow=ic,Re.get=Q,Re.invalidAt=vc,Re.isAfter=Wb,Re.isBefore=Xb,Re.isBetween=Yb,Re.isSame=Zb,Re.isSameOrAfter=$b,Re.isSameOrBefore=_b,Re.isValid=tc,Re.lang=Le,Re.locale=jc,Re.localeData=kc,Re.max=Ee,Re.min=De,Re.parsingFlags=uc,Re.set=R,Re.startOf=lc,Re.subtract=Ke,Re.toArray=qc,Re.toObject=rc,Re.toDate=pc,Re.toISOString=dc,Re.toJSON=sc,Re.toString=cc,Re.unix=oc,Re.valueOf=nc,Re.creationData=wc, +// Year +Re.year=ke,Re.isLeapYear=qa, +// Week Year +Re.weekYear=yc,Re.isoWeekYear=zc, +// Quarter +Re.quarter=Re.quarters=Ec, +// Month +Re.month=ja,Re.daysInMonth=ka, +// Week +Re.week=Re.weeks=Aa,Re.isoWeek=Re.isoWeeks=Ba,Re.weeksInYear=Bc,Re.isoWeeksInYear=Ac, +// Day +Re.date=Me,Re.day=Re.days=Ja,Re.weekday=Ka,Re.isoWeekday=La,Re.dayOfYear=Fc, +// Hour +Re.hour=Re.hours=ue, +// Minute +Re.minute=Re.minutes=Ne, +// Second +Re.second=Re.seconds=Oe, +// Millisecond +Re.millisecond=Re.milliseconds=Qe, +// Offset +Re.utcOffset=Bb,Re.utc=Db,Re.local=Eb,Re.parseZone=Fb,Re.hasAlignedHourOffset=Gb,Re.isDST=Hb,Re.isLocal=Jb,Re.isUtcOffset=Kb,Re.isUtc=Lb,Re.isUTC=Lb, +// Timezone +Re.zoneAbbr=Hc,Re.zoneName=Ic, +// Deprecations +Re.dates=w("dates accessor is deprecated. Use date instead.",Me),Re.months=w("months accessor is deprecated. Use month instead",ja),Re.years=w("years accessor is deprecated. Use year instead",ke),Re.zone=w("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",Cb),Re.isDSTShifted=w("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",Ib);var Se=Re,Te=B.prototype;Te.calendar=C,Te.longDateFormat=D,Te.invalidDate=E,Te.ordinal=F,Te.preparse=Lc,Te.postformat=Lc,Te.relativeTime=G,Te.pastFuture=H,Te.set=z, +// Month +Te.months=ea,Te.monthsShort=fa,Te.monthsParse=ha,Te.monthsRegex=ma,Te.monthsShortRegex=la, +// Week +Te.week=xa,Te.firstDayOfYear=za,Te.firstDayOfWeek=ya, +// Day of Week +Te.weekdays=Ea,Te.weekdaysMin=Ga,Te.weekdaysShort=Fa,Te.weekdaysParse=Ia,Te.weekdaysRegex=Ma,Te.weekdaysShortRegex=Na,Te.weekdaysMinRegex=Oa, +// Hours +Te.isPM=Ua,Te.meridiem=Va,Za("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===t(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}), +// Side effect imports +a.lang=w("moment.lang is deprecated. Use moment.locale instead.",Za),a.langData=w("moment.langData is deprecated. Use moment.localeData instead.",ab);var Ue=Math.abs,Ve=cd("ms"),We=cd("s"),Xe=cd("m"),Ye=cd("h"),Ze=cd("d"),$e=cd("w"),_e=cd("M"),af=cd("y"),bf=ed("milliseconds"),cf=ed("seconds"),df=ed("minutes"),ef=ed("hours"),ff=ed("days"),gf=ed("months"),hf=ed("years"),jf=Math.round,kf={s:45,// seconds to minute +m:45,// minutes to hour +h:22,// hours to day +d:26,// days to month +M:11},lf=Math.abs,mf=vb.prototype;mf.abs=Uc,mf.add=Wc,mf.subtract=Xc,mf.as=ad,mf.asMilliseconds=Ve,mf.asSeconds=We,mf.asMinutes=Xe,mf.asHours=Ye,mf.asDays=Ze,mf.asWeeks=$e,mf.asMonths=_e,mf.asYears=af,mf.valueOf=bd,mf._bubble=Zc,mf.get=dd,mf.milliseconds=bf,mf.seconds=cf,mf.minutes=df,mf.hours=ef,mf.days=ff,mf.weeks=fd,mf.months=gf,mf.years=hf,mf.humanize=kd,mf.toISOString=ld,mf.toString=ld,mf.toJSON=ld,mf.locale=jc,mf.localeData=kc, +// Deprecations +mf.toIsoString=w("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",ld),mf.lang=Le, +// Side effect imports +// FORMATTING +T("X",0,0,"unix"),T("x",0,0,"valueOf"), +// PARSING +Y("x",Rd),Y("X",Ud),aa("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),aa("x",function(a,b,c){c._d=new Date(t(a))}), +// Side effect imports +a.version="2.14.1",b(rb),a.fn=Se,a.min=tb,a.max=ub,a.now=Fe,a.utc=j,a.unix=Jc,a.months=Pc,a.isDate=f,a.locale=Za,a.invalid=n,a.duration=Mb,a.isMoment=r,a.weekdays=Rc,a.parseZone=Kc,a.localeData=ab,a.isDuration=wb,a.monthsShort=Qc,a.weekdaysMin=Tc,a.defineLocale=$a,a.updateLocale=_a,a.locales=bb,a.weekdaysShort=Sc,a.normalizeUnits=J,a.relativeTimeRounding=id,a.relativeTimeThreshold=jd,a.calendarFormat=Tb,a.prototype=Se;var nf=a;return nf});
@@ -0,0 +1,536 @@
+declare function moment(): moment.Moment; +declare function moment(date: number): moment.Moment; +declare function moment(date: number[]): moment.Moment; +declare function moment(date: string, format?: string, strict?: boolean): moment.Moment; +declare function moment(date: string, format?: string, language?: string, strict?: boolean): moment.Moment; +declare function moment(date: string, formats: string[], strict?: boolean): moment.Moment; +declare function moment(date: string, formats: string[], language?: string, strict?: boolean): moment.Moment; +declare function moment(date: string, specialFormat: () => void, strict?: boolean): moment.Moment; +declare function moment(date: string, specialFormat: () => void, language?: string, strict?: boolean): moment.Moment; +declare function moment(date: string, formatsIncludingSpecial: any[], strict?: boolean): moment.Moment; +declare function moment(date: string, formatsIncludingSpecial: any[], language?: string, strict?: boolean): moment.Moment; +declare function moment(date: Date): moment.Moment; +declare function moment(date: moment.Moment): moment.Moment; +declare function moment(date: Object): moment.Moment; + +declare namespace moment { + type formatFunction = () => string; + + interface MomentDateObject { + years?: number; + /* One digit */ + months?: number; + /* Day of the month */ + date?: number; + hours?: number; + minutes?: number; + seconds?: number; + milliseconds?: number; + } + + interface MomentLanguageData extends BaseMomentLanguage { + /** + * @param formatType should be L, LL, LLL, LLLL. + */ + longDateFormat(formatType: string): string; + } + + interface Duration { + humanize(withSuffix?: boolean): string; + + as(units: string): number; + + milliseconds(): number; + asMilliseconds(): number; + + seconds(): number; + asSeconds(): number; + + minutes(): number; + asMinutes(): number; + + hours(): number; + asHours(): number; + + days(): number; + asDays(): number; + + weeks(): number; + asWeeks(): number; + + months(): number; + asMonths(): number; + + years(): number; + asYears(): number; + + add(n: number, p: UnitOfTime): Duration; + add(n: number): Duration; + add(d: Duration): Duration; + + subtract(n: number, p: UnitOfTime): Duration; + subtract(n: number): Duration; + subtract(d: Duration): Duration; + + toISOString(): string; + toJSON(): string; + } + + interface MomentInput { + /** Year */ + years?: number; + /** Year */ + year?: number; + /** Year */ + y?: number; + + /** Month */ + months?: number; + /** Month */ + month?: number; + /** Month */ + M?: number; + + /** Week */ + weeks?: number; + /** Week */ + week?: number; + /** Week */ + w?: number; + + /** Day/Date */ + days?: number; + /** Day/Date */ + day?: number; + /** Day/Date */ + date?: number; + /** Day/Date */ + d?: number; + + /** Hour */ + hours?: number; + /** Hour */ + hour?: number; + /** Hour */ + h?: number; + + /** Minute */ + minutes?: number; + /** Minute */ + minute?: number; + /** Minute */ + m?: number; + + /** Second */ + seconds?: number; + /** Second */ + second?: number; + /** Second */ + s?: number; + + /** Millisecond */ + milliseconds?: number; + /** Millisecond */ + millisecond?: number; + /** Millisecond */ + ms?: number; + } + + interface MomentCalendar { + lastDay?: string | formatFunction; + sameDay?: string | formatFunction; + nextDay?: string | formatFunction; + lastWeek?: string | formatFunction; + nextWeek?: string | formatFunction; + sameElse?: string | formatFunction; + } + + interface MomentRelativeTime { + future: any; + past: any; + s: any; + m: any; + mm: any; + h: any; + hh: any; + d: any; + dd: any; + M: any; + MM: any; + y: any; + yy: any; + } + + interface MomentLongDateFormat { + L: string; + LL: string; + LLL: string; + LLLL: string; + LT: string; + LTS: string; + l?: string; + ll?: string; + lll?: string; + llll?: string; + lt?: string; + lts?: string; + } + + interface MomentParsingFlags { + empty: boolean; + unusedTokens: string[]; + unusedInput: string[]; + overflow: number; + charsLeftOver: number; + nullInput: boolean; + invalidMonth?: string; + invalidFormat: boolean; + userInvalidated: boolean; + iso: boolean; + parsedDateParts: any[]; + meridiem?: string; + } + + interface BaseMomentLanguage { + months?: any; + monthsShort?: any; + weekdays?: any; + weekdaysShort?: any; + weekdaysMin?: any; + relativeTime?: MomentRelativeTime; + meridiem?: (hour: number, minute: number, isLowercase: boolean) => string; + calendar?: MomentCalendar; + ordinal?: (num: number) => string; + } + + interface MomentLanguage extends BaseMomentLanguage { + longDateFormat?: MomentLongDateFormat; + } + + type UnitOfTime = ("year" | "years" | "y" | + "quarter" | "quarters" | "Q" | + "month" | "months" | "M" | + "week" | "weeks" | "w" | + "day" | "days" | "d" | + "hour" | "hours" | "h" | + "minute" | "minutes" | "m" | + "second" | "seconds" | "s" | + "millisecond" | "milliseconds" | "ms"); + + interface Moment { + format(format: string): string; + format(): string; + + fromNow(withoutSuffix?: boolean): string; + + startOf(unitOfTime: UnitOfTime): Moment; + endOf(unitOfTime: UnitOfTime): Moment; + + /** + * Mutates the original moment by adding time. (deprecated in 2.8.0) + * + * @param unitOfTime the unit of time you want to add (eg "years" / "hours" etc) + * @param amount the amount you want to add + */ + add(unitOfTime: UnitOfTime, amount: number): Moment; + /** + * Mutates the original moment by adding time. + * + * @param amount the amount you want to add + * @param unitOfTime the unit of time you want to add (eg "years" / "hours" etc) + */ + add(amount: number, unitOfTime: UnitOfTime): Moment; + /** + * Mutates the original moment by adding time. Note that the order of arguments can be flipped. + * + * @param amount the amount you want to add + * @param unitOfTime the unit of time you want to add (eg "years" / "hours" etc) + */ + add(amount: string, unitOfTime: UnitOfTime): Moment; + /** + * Mutates the original moment by adding time. + * + * @param objectLiteral an object literal that describes multiple time units {days:7,months:1} + */ + add(objectLiteral: MomentInput): Moment; + /** + * Mutates the original moment by adding time. + * + * @param duration a length of time + */ + add(duration: Duration): Moment; + + /** + * Mutates the original moment by subtracting time. (deprecated in 2.8.0) + * + * @param unitOfTime the unit of time you want to subtract (eg "years" / "hours" etc) + * @param amount the amount you want to subtract + */ + subtract(unitOfTime: UnitOfTime, amount: number): Moment; + /** + * Mutates the original moment by subtracting time. + * + * @param unitOfTime the unit of time you want to subtract (eg "years" / "hours" etc) + * @param amount the amount you want to subtract + */ + subtract(amount: number, unitOfTime: UnitOfTime): Moment; + /** + * Mutates the original moment by subtracting time. Note that the order of arguments can be flipped. + * + * @param amount the amount you want to add + * @param unitOfTime the unit of time you want to subtract (eg "years" / "hours" etc) + */ + subtract(amount: string, unitOfTime: UnitOfTime): Moment; + /** + * Mutates the original moment by subtracting time. + * + * @param objectLiteral an object literal that describes multiple time units {days:7,months:1} + */ + subtract(objectLiteral: MomentInput): Moment; + /** + * Mutates the original moment by subtracting time. + * + * @param duration a length of time + */ + subtract(duration: Duration): Moment; + + calendar(): string; + calendar(start: Moment): string; + calendar(start: Moment, formats: MomentCalendar): string; + + clone(): Moment; + + /** + * @return Unix timestamp, or milliseconds since the epoch. + */ + valueOf(): number; + + local(): Moment; // current date/time in local mode + + utc(): Moment; // current date/time in UTC mode + + isValid(): boolean; + invalidAt(): number; + + parsingFlags(): MomentParsingFlags; + + year(y: number): Moment; + year(): number; + quarter(): number; + quarter(q: number): Moment; + month(M: number): Moment; + month(M: string): Moment; + month(): number; + day(d: number): Moment; + day(d: string): Moment; + day(): number; + date(d: number): Moment; + date(): number; + hour(h: number): Moment; + hour(): number; + hours(h: number): Moment; + hours(): number; + minute(m: number): Moment; + minute(): number; + minutes(m: number): Moment; + minutes(): number; + second(s: number): Moment; + second(): number; + seconds(s: number): Moment; + seconds(): number; + millisecond(ms: number): Moment; + millisecond(): number; + milliseconds(ms: number): Moment; + milliseconds(): number; + weekday(): number; + weekday(d: number): Moment; + isoWeekday(): number; + isoWeekday(d: number): Moment; + weekYear(): number; + weekYear(d: number): Moment; + isoWeekYear(): number; + isoWeekYear(d: number): Moment; + week(): number; + week(d: number): Moment; + weeks(): number; + weeks(d: number): Moment; + isoWeek(): number; + isoWeek(d: number): Moment; + isoWeeks(): number; + isoWeeks(d: number): Moment; + weeksInYear(): number; + isoWeeksInYear(): number; + dayOfYear(): number; + dayOfYear(d: number): Moment; + + from(f: Moment | string | number | Date | number[], suffix?: boolean): string; + to(f: Moment | string | number | Date | number[], suffix?: boolean): string; + toNow(withoutPrefix?: boolean): string; + + diff(b: Moment): number; + diff(b: Moment, unitOfTime: UnitOfTime): number; + diff(b: Moment, unitOfTime: UnitOfTime, precise: boolean): number; + + toArray(): number[]; + toDate(): Date; + toISOString(): string; + toJSON(): string; + unix(): number; + + isLeapYear(): boolean; + zone(): number; + zone(b: number): Moment; + zone(b: string): Moment; + utcOffset(): number; + utcOffset(b: number): Moment; + utcOffset(b: string): Moment; + daysInMonth(): number; + isDST(): boolean; + + isBefore(): boolean; + isBefore(b: Moment | string | number | Date | number[], granularity?: string): boolean; + + isAfter(): boolean; + isAfter(b: Moment | string | number | Date | number[], granularity?: string): boolean; + + isSame(b: Moment | string | number | Date | number[], granularity?: string): boolean; + isSameOrAfter(b: Moment | string | number | Date | number[], granularity?: string): boolean; + isSameOrBefore(b: Moment | string | number | Date | number[], granularity?: string): boolean; + + isBetween(a: Moment | string | number | Date | number[], b: Moment | string | number | Date | number[], granularity?: string, inclusivity?: string): boolean; + + // Deprecated as of 2.8.0. + lang(language: string): Moment; + lang(reset: boolean): Moment; + lang(): MomentLanguage; + + locale(language: string): Moment; + locale(reset: boolean): Moment; + locale(): string; + + localeData(language: string): Moment; + localeData(reset: boolean): Moment; + localeData(): MomentLanguage; + + defineLocale(language: string, locale: MomentLanguage): MomentLanguage; + updateLocale(language: string, locale: MomentLanguage): MomentLanguage; + + // Deprecated as of 2.7.0. + max(date: Moment | string | number | Date | any[]): Moment; + max(date: string, format: string): Moment; + + // Deprecated as of 2.7.0. + min(date: Moment | string | number | Date | any[]): Moment; + min(date: string, format: string): Moment; + + get(unit: UnitOfTime): number; + set(unit: UnitOfTime, value: number): Moment; + set(objectLiteral: MomentInput): Moment; + + /*This returns an object containing year, month, day-of-month, hour, minute, seconds, milliseconds.*/ + //Works with version 2.10.5+ + toObject(): MomentDateObject; + } + + export var version: string; + export var fn: Moment; + + export function utc(): Moment; + export function utc(date: number): Moment; + export function utc(date: number[]): Moment; + export function utc(date: string, format?: string, strict?: boolean): Moment; + export function utc(date: string, format?: string, language?: string, strict?: boolean): Moment; + export function utc(date: string, formats: string[], strict?: boolean): Moment; + export function utc(date: string, formats: string[], language?: string, strict?: boolean): Moment; + export function utc(date: Date): Moment; + export function utc(date: Moment): Moment; + export function utc(date: Object): Moment; + + export function unix(timestamp: number): Moment; + + export function invalid(parsingFlags?: Object): Moment; + export function isMoment(): boolean; + export function isMoment(m: any): m is Moment; + export function isDate(m: any): m is Date; + export function isDuration(): boolean; + export function isDuration(d: any): d is Duration; + + // Deprecated in 2.8.0. + export function lang(language?: string): string; + export function lang(language?: string, definition?: MomentLanguage): string; + + export function locale(language?: string): string; + export function locale(language?: string[]): string; + export function locale(language?: string, definition?: MomentLanguage): string; + + export function localeData(language?: string): MomentLanguageData; + + export function updateLocale(language: string, locale: MomentLanguage): MomentLanguage; + + export var longDateFormat: any; + export var relativeTime: any; + export var meridiem: (hour: number, minute: number, isLowercase: boolean) => string; + export var calendar: any; + export var ordinal: (num: number) => string; + + export function duration(milliseconds: Number): Duration; + export function duration(num: Number, unitOfTime: UnitOfTime): Duration; + export function duration(input: MomentInput): Duration; + export function duration(object: any): Duration; + export function duration(): Duration; + + export function parseZone(date: string): Moment; + + export function months(): string[]; + export function months(index: number): string; + export function months(format: string): string[]; + export function months(format: string, index: number): string; + export function monthsShort(): string[]; + export function monthsShort(index: number): string; + export function monthsShort(format: string): string[]; + export function monthsShort(format: string, index: number): string; + + export function weekdays(): string[]; + export function weekdays(index: number): string; + export function weekdays(format: string): string[]; + export function weekdays(format: string, index: number): string; + export function weekdays(localeSorted: boolean): string[]; + export function weekdays(localeSorted: boolean, index: number): string; + export function weekdays(localeSorted: boolean, format: string): string[]; + export function weekdays(localeSorted: boolean, format: string, index: number): string; + export function weekdaysShort(): string[]; + export function weekdaysShort(index: number): string; + export function weekdaysShort(format: string): string[]; + export function weekdaysShort(format: string, index: number): string; + export function weekdaysShort(localeSorted: boolean): string[]; + export function weekdaysShort(localeSorted: boolean, index: number): string; + export function weekdaysShort(localeSorted: boolean, format: string): string[]; + export function weekdaysShort(localeSorted: boolean, format: string, index: number): string; + export function weekdaysMin(): string[]; + export function weekdaysMin(index: number): string; + export function weekdaysMin(format: string): string[]; + export function weekdaysMin(format: string, index: number): string; + export function weekdaysMin(localeSorted: boolean): string[]; + export function weekdaysMin(localeSorted: boolean, index: number): string; + export function weekdaysMin(localeSorted: boolean, format: string): string[]; + export function weekdaysMin(localeSorted: boolean, format: string, index: number): string; + + export function min(...moments: Moment[]): Moment; + export function max(...moments: Moment[]): Moment; + + export function normalizeUnits(unit: string): string; + export function relativeTimeThreshold(threshold: string): number | boolean; + export function relativeTimeThreshold(threshold: string, limit: number): boolean; + export function relativeTimeRounding(fn: (num: number) => number): boolean; + export function relativeTimeRounding(): (num: number) => number; + export function calendarFormat(m: Moment, now: Moment): string; + + /** + * Constant used to enable explicit ISO_8601 format parsing. + */ + export function ISO_8601(): void; + + export var defaultFormat: string; +} + +export = moment;
@@ -0,0 +1,4195 @@
+//! moment.js +//! version : 2.14.1 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com + +;(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + global.moment = factory() +}(this, function () { 'use strict'; + + var hookCallback; + + function utils_hooks__hooks () { + return hookCallback.apply(null, arguments); + } + + // This is done to register the method called with moment() + // without creating circular dependencies. + function setHookCallback (callback) { + hookCallback = callback; + } + + function isArray(input) { + return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]'; + } + + function isObject(input) { + return Object.prototype.toString.call(input) === '[object Object]'; + } + + function isObjectEmpty(obj) { + var k; + for (k in obj) { + // even if its not own property I'd still call it non-empty + return false; + } + return true; + } + + function isDate(input) { + return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]'; + } + + function map(arr, fn) { + var res = [], i; + for (i = 0; i < arr.length; ++i) { + res.push(fn(arr[i], i)); + } + return res; + } + + function hasOwnProp(a, b) { + return Object.prototype.hasOwnProperty.call(a, b); + } + + function extend(a, b) { + for (var i in b) { + if (hasOwnProp(b, i)) { + a[i] = b[i]; + } + } + + if (hasOwnProp(b, 'toString')) { + a.toString = b.toString; + } + + if (hasOwnProp(b, 'valueOf')) { + a.valueOf = b.valueOf; + } + + return a; + } + + function create_utc__createUTC (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, true).utc(); + } + + function defaultParsingFlags() { + // We need to deep clone this object. + return { + empty : false, + unusedTokens : [], + unusedInput : [], + overflow : -2, + charsLeftOver : 0, + nullInput : false, + invalidMonth : null, + invalidFormat : false, + userInvalidated : false, + iso : false, + parsedDateParts : [], + meridiem : null + }; + } + + function getParsingFlags(m) { + if (m._pf == null) { + m._pf = defaultParsingFlags(); + } + return m._pf; + } + + var some; + if (Array.prototype.some) { + some = Array.prototype.some; + } else { + some = function (fun) { + var t = Object(this); + var len = t.length >>> 0; + + for (var i = 0; i < len; i++) { + if (i in t && fun.call(this, t[i], i, t)) { + return true; + } + } + + return false; + }; + } + + function valid__isValid(m) { + if (m._isValid == null) { + var flags = getParsingFlags(m); + var parsedParts = some.call(flags.parsedDateParts, function (i) { + return i != null; + }); + m._isValid = !isNaN(m._d.getTime()) && + flags.overflow < 0 && + !flags.empty && + !flags.invalidMonth && + !flags.invalidWeekday && + !flags.nullInput && + !flags.invalidFormat && + !flags.userInvalidated && + (!flags.meridiem || (flags.meridiem && parsedParts)); + + if (m._strict) { + m._isValid = m._isValid && + flags.charsLeftOver === 0 && + flags.unusedTokens.length === 0 && + flags.bigHour === undefined; + } + } + return m._isValid; + } + + function valid__createInvalid (flags) { + var m = create_utc__createUTC(NaN); + if (flags != null) { + extend(getParsingFlags(m), flags); + } + else { + getParsingFlags(m).userInvalidated = true; + } + + return m; + } + + function isUndefined(input) { + return input === void 0; + } + + // Plugins that add properties should also add the key here (null value), + // so we can properly clone ourselves. + var momentProperties = utils_hooks__hooks.momentProperties = []; + + function copyConfig(to, from) { + var i, prop, val; + + if (!isUndefined(from._isAMomentObject)) { + to._isAMomentObject = from._isAMomentObject; + } + if (!isUndefined(from._i)) { + to._i = from._i; + } + if (!isUndefined(from._f)) { + to._f = from._f; + } + if (!isUndefined(from._l)) { + to._l = from._l; + } + if (!isUndefined(from._strict)) { + to._strict = from._strict; + } + if (!isUndefined(from._tzm)) { + to._tzm = from._tzm; + } + if (!isUndefined(from._isUTC)) { + to._isUTC = from._isUTC; + } + if (!isUndefined(from._offset)) { + to._offset = from._offset; + } + if (!isUndefined(from._pf)) { + to._pf = getParsingFlags(from); + } + if (!isUndefined(from._locale)) { + to._locale = from._locale; + } + + if (momentProperties.length > 0) { + for (i in momentProperties) { + prop = momentProperties[i]; + val = from[prop]; + if (!isUndefined(val)) { + to[prop] = val; + } + } + } + + return to; + } + + var updateInProgress = false; + + // Moment prototype object + function Moment(config) { + copyConfig(this, config); + this._d = new Date(config._d != null ? config._d.getTime() : NaN); + // Prevent infinite loop in case updateOffset creates new moment + // objects. + if (updateInProgress === false) { + updateInProgress = true; + utils_hooks__hooks.updateOffset(this); + updateInProgress = false; + } + } + + function isMoment (obj) { + return obj instanceof Moment || (obj != null && obj._isAMomentObject != null); + } + + function absFloor (number) { + if (number < 0) { + // -0 -> 0 + return Math.ceil(number) || 0; + } else { + return Math.floor(number); + } + } + + function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; + + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + value = absFloor(coercedNumber); + } + + return value; + } + + // compare two arrays, return the number of differences + function compareArrays(array1, array2, dontConvert) { + var len = Math.min(array1.length, array2.length), + lengthDiff = Math.abs(array1.length - array2.length), + diffs = 0, + i; + for (i = 0; i < len; i++) { + if ((dontConvert && array1[i] !== array2[i]) || + (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { + diffs++; + } + } + return diffs + lengthDiff; + } + + function warn(msg) { + if (utils_hooks__hooks.suppressDeprecationWarnings === false && + (typeof console !== 'undefined') && console.warn) { + console.warn('Deprecation warning: ' + msg); + } + } + + function deprecate(msg, fn) { + var firstTime = true; + + return extend(function () { + if (utils_hooks__hooks.deprecationHandler != null) { + utils_hooks__hooks.deprecationHandler(null, msg); + } + if (firstTime) { + warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack); + firstTime = false; + } + return fn.apply(this, arguments); + }, fn); + } + + var deprecations = {}; + + function deprecateSimple(name, msg) { + if (utils_hooks__hooks.deprecationHandler != null) { + utils_hooks__hooks.deprecationHandler(name, msg); + } + if (!deprecations[name]) { + warn(msg); + deprecations[name] = true; + } + } + + utils_hooks__hooks.suppressDeprecationWarnings = false; + utils_hooks__hooks.deprecationHandler = null; + + function isFunction(input) { + return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]'; + } + + function locale_set__set (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (isFunction(prop)) { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + this._config = config; + // Lenient ordinal parsing accepts just a number in addition to + // number + (possibly) stuff coming from _ordinalParseLenient. + this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source); + } + + function mergeConfigs(parentConfig, childConfig) { + var res = extend({}, parentConfig), prop; + for (prop in childConfig) { + if (hasOwnProp(childConfig, prop)) { + if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) { + res[prop] = {}; + extend(res[prop], parentConfig[prop]); + extend(res[prop], childConfig[prop]); + } else if (childConfig[prop] != null) { + res[prop] = childConfig[prop]; + } else { + delete res[prop]; + } + } + } + for (prop in parentConfig) { + if (hasOwnProp(parentConfig, prop) && + !hasOwnProp(childConfig, prop) && + isObject(parentConfig[prop])) { + // make sure changes to properties don't modify parent config + res[prop] = extend({}, res[prop]); + } + } + return res; + } + + function Locale(config) { + if (config != null) { + this.set(config); + } + } + + var keys; + + if (Object.keys) { + keys = Object.keys; + } else { + keys = function (obj) { + var i, res = []; + for (i in obj) { + if (hasOwnProp(obj, i)) { + res.push(i); + } + } + return res; + }; + } + + var defaultCalendar = { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }; + + function locale_calendar__calendar (key, mom, now) { + var output = this._calendar[key] || this._calendar['sameElse']; + return isFunction(output) ? output.call(mom, now) : output; + } + + var defaultLongDateFormat = { + LTS : 'h:mm:ss A', + LT : 'h:mm A', + L : 'MM/DD/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY h:mm A', + LLLL : 'dddd, MMMM D, YYYY h:mm A' + }; + + function longDateFormat (key) { + var format = this._longDateFormat[key], + formatUpper = this._longDateFormat[key.toUpperCase()]; + + if (format || !formatUpper) { + return format; + } + + this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) { + return val.slice(1); + }); + + return this._longDateFormat[key]; + } + + var defaultInvalidDate = 'Invalid date'; + + function invalidDate () { + return this._invalidDate; + } + + var defaultOrdinal = '%d'; + var defaultOrdinalParse = /\d{1,2}/; + + function ordinal (number) { + return this._ordinal.replace('%d', number); + } + + var defaultRelativeTime = { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }; + + function relative__relativeTime (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (isFunction(output)) ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); + } + + function pastFuture (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return isFunction(format) ? format(output) : format.replace(/%s/i, output); + } + + var aliases = {}; + + function addUnitAlias (unit, shorthand) { + var lowerCase = unit.toLowerCase(); + aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit; + } + + function normalizeUnits(units) { + return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined; + } + + function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; + + for (prop in inputObject) { + if (hasOwnProp(inputObject, prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } + + return normalizedInput; + } + + var priorities = {}; + + function addUnitPriority(unit, priority) { + priorities[unit] = priority; + } + + function getPrioritizedUnits(unitsObj) { + var units = []; + for (var u in unitsObj) { + units.push({unit: u, priority: priorities[u]}); + } + units.sort(function (a, b) { + return a.priority - b.priority; + }); + return units; + } + + function makeGetSet (unit, keepTime) { + return function (value) { + if (value != null) { + get_set__set(this, unit, value); + utils_hooks__hooks.updateOffset(this, keepTime); + return this; + } else { + return get_set__get(this, unit); + } + }; + } + + function get_set__get (mom, unit) { + return mom.isValid() ? + mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN; + } + + function get_set__set (mom, unit, value) { + if (mom.isValid()) { + mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); + } + } + + // MOMENTS + + function stringGet (units) { + units = normalizeUnits(units); + if (isFunction(this[units])) { + return this[units](); + } + return this; + } + + + function stringSet (units, value) { + if (typeof units === 'object') { + units = normalizeObjectUnits(units); + var prioritized = getPrioritizedUnits(units); + for (var i = 0; i < prioritized.length; i++) { + this[prioritized[i].unit](units[prioritized[i].unit]); + } + } else { + units = normalizeUnits(units); + if (isFunction(this[units])) { + return this[units](value); + } + } + return this; + } + + function zeroFill(number, targetLength, forceSign) { + var absNumber = '' + Math.abs(number), + zerosToFill = targetLength - absNumber.length, + sign = number >= 0; + return (sign ? (forceSign ? '+' : '') : '-') + + Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber; + } + + var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g; + + var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g; + + var formatFunctions = {}; + + var formatTokenFunctions = {}; + + // token: 'M' + // padded: ['MM', 2] + // ordinal: 'Mo' + // callback: function () { this.month() + 1 } + function addFormatToken (token, padded, ordinal, callback) { + var func = callback; + if (typeof callback === 'string') { + func = function () { + return this[callback](); + }; + } + if (token) { + formatTokenFunctions[token] = func; + } + if (padded) { + formatTokenFunctions[padded[0]] = function () { + return zeroFill(func.apply(this, arguments), padded[1], padded[2]); + }; + } + if (ordinal) { + formatTokenFunctions[ordinal] = function () { + return this.localeData().ordinal(func.apply(this, arguments), token); + }; + } + } + + function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + return input.replace(/^\[|\]$/g, ''); + } + return input.replace(/\\/g, ''); + } + + function makeFormatFunction(format) { + var array = format.match(formattingTokens), i, length; + + for (i = 0, length = array.length; i < length; i++) { + if (formatTokenFunctions[array[i]]) { + array[i] = formatTokenFunctions[array[i]]; + } else { + array[i] = removeFormattingTokens(array[i]); + } + } + + return function (mom) { + var output = '', i; + for (i = 0; i < length; i++) { + output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; + } + return output; + }; + } + + // format date using native date object + function formatMoment(m, format) { + if (!m.isValid()) { + return m.localeData().invalidDate(); + } + + format = expandFormat(format, m.localeData()); + formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format); + + return formatFunctions[format](m); + } + + function expandFormat(format, locale) { + var i = 5; + + function replaceLongDateFormatTokens(input) { + return locale.longDateFormat(input) || input; + } + + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } + + return format; + } + + var match1 = /\d/; // 0 - 9 + var match2 = /\d\d/; // 00 - 99 + var match3 = /\d{3}/; // 000 - 999 + var match4 = /\d{4}/; // 0000 - 9999 + var match6 = /[+-]?\d{6}/; // -999999 - 999999 + var match1to2 = /\d\d?/; // 0 - 99 + var match3to4 = /\d\d\d\d?/; // 999 - 9999 + var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999 + var match1to3 = /\d{1,3}/; // 0 - 999 + var match1to4 = /\d{1,4}/; // 0 - 9999 + var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999 + + var matchUnsigned = /\d+/; // 0 - inf + var matchSigned = /[+-]?\d+/; // -inf - inf + + var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z + var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z + + var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123 + + // any word (or two) characters or numbers including two/three word month in arabic. + // includes scottish gaelic two word and hyphenated months + var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i; + + + var regexes = {}; + + function addRegexToken (token, regex, strictRegex) { + regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) { + return (isStrict && strictRegex) ? strictRegex : regex; + }; + } + + function getParseRegexForToken (token, config) { + if (!hasOwnProp(regexes, token)) { + return new RegExp(unescapeFormat(token)); + } + + return regexes[token](config._strict, config._locale); + } + + // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript + function unescapeFormat(s) { + return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + })); + } + + function regexEscape(s) { + return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + } + + var tokens = {}; + + function addParseToken (token, callback) { + var i, func = callback; + if (typeof token === 'string') { + token = [token]; + } + if (typeof callback === 'number') { + func = function (input, array) { + array[callback] = toInt(input); + }; + } + for (i = 0; i < token.length; i++) { + tokens[token[i]] = func; + } + } + + function addWeekParseToken (token, callback) { + addParseToken(token, function (input, array, config, token) { + config._w = config._w || {}; + callback(input, config._w, config, token); + }); + } + + function addTimeToArrayFromToken(token, input, config) { + if (input != null && hasOwnProp(tokens, token)) { + tokens[token](input, config._a, config, token); + } + } + + var YEAR = 0; + var MONTH = 1; + var DATE = 2; + var HOUR = 3; + var MINUTE = 4; + var SECOND = 5; + var MILLISECOND = 6; + var WEEK = 7; + var WEEKDAY = 8; + + var indexOf; + + if (Array.prototype.indexOf) { + indexOf = Array.prototype.indexOf; + } else { + indexOf = function (o) { + // I know + var i; + for (i = 0; i < this.length; ++i) { + if (this[i] === o) { + return i; + } + } + return -1; + }; + } + + function daysInMonth(year, month) { + return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); + } + + // FORMATTING + + addFormatToken('M', ['MM', 2], 'Mo', function () { + return this.month() + 1; + }); + + addFormatToken('MMM', 0, 0, function (format) { + return this.localeData().monthsShort(this, format); + }); + + addFormatToken('MMMM', 0, 0, function (format) { + return this.localeData().months(this, format); + }); + + // ALIASES + + addUnitAlias('month', 'M'); + + // PRIORITY + + addUnitPriority('month', 8); + + // PARSING + + addRegexToken('M', match1to2); + addRegexToken('MM', match1to2, match2); + addRegexToken('MMM', function (isStrict, locale) { + return locale.monthsShortRegex(isStrict); + }); + addRegexToken('MMMM', function (isStrict, locale) { + return locale.monthsRegex(isStrict); + }); + + addParseToken(['M', 'MM'], function (input, array) { + array[MONTH] = toInt(input) - 1; + }); + + addParseToken(['MMM', 'MMMM'], function (input, array, config, token) { + var month = config._locale.monthsParse(input, token, config._strict); + // if we didn't find a month name, mark the date as invalid. + if (month != null) { + array[MONTH] = month; + } else { + getParsingFlags(config).invalidMonth = input; + } + }); + + // LOCALES + + var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/; + var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'); + function localeMonths (m, format) { + return isArray(this._months) ? this._months[m.month()] : + this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()]; + } + + var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'); + function localeMonthsShort (m, format) { + return isArray(this._monthsShort) ? this._monthsShort[m.month()] : + this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()]; + } + + function units_month__handleStrictParse(monthName, format, strict) { + var i, ii, mom, llc = monthName.toLocaleLowerCase(); + if (!this._monthsParse) { + // this is not used + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + for (i = 0; i < 12; ++i) { + mom = create_utc__createUTC([2000, i]); + this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase(); + this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase(); + } + } + + if (strict) { + if (format === 'MMM') { + ii = indexOf.call(this._shortMonthsParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._longMonthsParse, llc); + return ii !== -1 ? ii : null; + } + } else { + if (format === 'MMM') { + ii = indexOf.call(this._shortMonthsParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._longMonthsParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._longMonthsParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortMonthsParse, llc); + return ii !== -1 ? ii : null; + } + } + } + + function localeMonthsParse (monthName, format, strict) { + var i, mom, regex; + + if (this._monthsParseExact) { + return units_month__handleStrictParse.call(this, monthName, format, strict); + } + + if (!this._monthsParse) { + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + } + + // TODO: add sorting + // Sorting makes sure if one month (or abbr) is a prefix of another + // see sorting in computeMonthsParse + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = create_utc__createUTC([2000, i]); + if (strict && !this._longMonthsParse[i]) { + this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i'); + this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i'); + } + if (!strict && !this._monthsParse[i]) { + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) { + return i; + } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) { + return i; + } else if (!strict && this._monthsParse[i].test(monthName)) { + return i; + } + } + } + + // MOMENTS + + function setMonth (mom, value) { + var dayOfMonth; + + if (!mom.isValid()) { + // No op + return mom; + } + + if (typeof value === 'string') { + if (/^\d+$/.test(value)) { + value = toInt(value); + } else { + value = mom.localeData().monthsParse(value); + // TODO: Another silent failure? + if (typeof value !== 'number') { + return mom; + } + } + } + + dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value)); + mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); + return mom; + } + + function getSetMonth (value) { + if (value != null) { + setMonth(this, value); + utils_hooks__hooks.updateOffset(this, true); + return this; + } else { + return get_set__get(this, 'Month'); + } + } + + function getDaysInMonth () { + return daysInMonth(this.year(), this.month()); + } + + var defaultMonthsShortRegex = matchWord; + function monthsShortRegex (isStrict) { + if (this._monthsParseExact) { + if (!hasOwnProp(this, '_monthsRegex')) { + computeMonthsParse.call(this); + } + if (isStrict) { + return this._monthsShortStrictRegex; + } else { + return this._monthsShortRegex; + } + } else { + if (!hasOwnProp(this, '_monthsShortRegex')) { + this._monthsShortRegex = defaultMonthsShortRegex; + } + return this._monthsShortStrictRegex && isStrict ? + this._monthsShortStrictRegex : this._monthsShortRegex; + } + } + + var defaultMonthsRegex = matchWord; + function monthsRegex (isStrict) { + if (this._monthsParseExact) { + if (!hasOwnProp(this, '_monthsRegex')) { + computeMonthsParse.call(this); + } + if (isStrict) { + return this._monthsStrictRegex; + } else { + return this._monthsRegex; + } + } else { + if (!hasOwnProp(this, '_monthsRegex')) { + this._monthsRegex = defaultMonthsRegex; + } + return this._monthsStrictRegex && isStrict ? + this._monthsStrictRegex : this._monthsRegex; + } + } + + function computeMonthsParse () { + function cmpLenRev(a, b) { + return b.length - a.length; + } + + var shortPieces = [], longPieces = [], mixedPieces = [], + i, mom; + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = create_utc__createUTC([2000, i]); + shortPieces.push(this.monthsShort(mom, '')); + longPieces.push(this.months(mom, '')); + mixedPieces.push(this.months(mom, '')); + mixedPieces.push(this.monthsShort(mom, '')); + } + // Sorting makes sure if one month (or abbr) is a prefix of another it + // will match the longer piece. + shortPieces.sort(cmpLenRev); + longPieces.sort(cmpLenRev); + mixedPieces.sort(cmpLenRev); + for (i = 0; i < 12; i++) { + shortPieces[i] = regexEscape(shortPieces[i]); + longPieces[i] = regexEscape(longPieces[i]); + } + for (i = 0; i < 24; i++) { + mixedPieces[i] = regexEscape(mixedPieces[i]); + } + + this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); + this._monthsShortRegex = this._monthsRegex; + this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); + this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); + } + + // FORMATTING + + addFormatToken('Y', 0, 0, function () { + var y = this.year(); + return y <= 9999 ? '' + y : '+' + y; + }); + + addFormatToken(0, ['YY', 2], 0, function () { + return this.year() % 100; + }); + + addFormatToken(0, ['YYYY', 4], 0, 'year'); + addFormatToken(0, ['YYYYY', 5], 0, 'year'); + addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); + + // ALIASES + + addUnitAlias('year', 'y'); + + // PRIORITIES + + addUnitPriority('year', 1); + + // PARSING + + addRegexToken('Y', matchSigned); + addRegexToken('YY', match1to2, match2); + addRegexToken('YYYY', match1to4, match4); + addRegexToken('YYYYY', match1to6, match6); + addRegexToken('YYYYYY', match1to6, match6); + + addParseToken(['YYYYY', 'YYYYYY'], YEAR); + addParseToken('YYYY', function (input, array) { + array[YEAR] = input.length === 2 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input); + }); + addParseToken('YY', function (input, array) { + array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input); + }); + addParseToken('Y', function (input, array) { + array[YEAR] = parseInt(input, 10); + }); + + // HELPERS + + function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; + } + + function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + } + + // HOOKS + + utils_hooks__hooks.parseTwoDigitYear = function (input) { + return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); + }; + + // MOMENTS + + var getSetYear = makeGetSet('FullYear', true); + + function getIsLeapYear () { + return isLeapYear(this.year()); + } + + function createDate (y, m, d, h, M, s, ms) { + //can't just apply() to create a date: + //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply + var date = new Date(y, m, d, h, M, s, ms); + + //the date constructor remaps years 0-99 to 1900-1999 + if (y < 100 && y >= 0 && isFinite(date.getFullYear())) { + date.setFullYear(y); + } + return date; + } + + function createUTCDate (y) { + var date = new Date(Date.UTC.apply(null, arguments)); + + //the Date.UTC function remaps years 0-99 to 1900-1999 + if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) { + date.setUTCFullYear(y); + } + return date; + } + + // start-of-first-week - start-of-year + function firstWeekOffset(year, dow, doy) { + var // first-week day -- which january is always in the first week (4 for iso, 1 for other) + fwd = 7 + dow - doy, + // first-week day local weekday -- which local weekday is fwd + fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7; + + return -fwdlw + fwd - 1; + } + + //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday + function dayOfYearFromWeeks(year, week, weekday, dow, doy) { + var localWeekday = (7 + weekday - dow) % 7, + weekOffset = firstWeekOffset(year, dow, doy), + dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset, + resYear, resDayOfYear; + + if (dayOfYear <= 0) { + resYear = year - 1; + resDayOfYear = daysInYear(resYear) + dayOfYear; + } else if (dayOfYear > daysInYear(year)) { + resYear = year + 1; + resDayOfYear = dayOfYear - daysInYear(year); + } else { + resYear = year; + resDayOfYear = dayOfYear; + } + + return { + year: resYear, + dayOfYear: resDayOfYear + }; + } + + function weekOfYear(mom, dow, doy) { + var weekOffset = firstWeekOffset(mom.year(), dow, doy), + week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1, + resWeek, resYear; + + if (week < 1) { + resYear = mom.year() - 1; + resWeek = week + weeksInYear(resYear, dow, doy); + } else if (week > weeksInYear(mom.year(), dow, doy)) { + resWeek = week - weeksInYear(mom.year(), dow, doy); + resYear = mom.year() + 1; + } else { + resYear = mom.year(); + resWeek = week; + } + + return { + week: resWeek, + year: resYear + }; + } + + function weeksInYear(year, dow, doy) { + var weekOffset = firstWeekOffset(year, dow, doy), + weekOffsetNext = firstWeekOffset(year + 1, dow, doy); + return (daysInYear(year) - weekOffset + weekOffsetNext) / 7; + } + + // FORMATTING + + addFormatToken('w', ['ww', 2], 'wo', 'week'); + addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); + + // ALIASES + + addUnitAlias('week', 'w'); + addUnitAlias('isoWeek', 'W'); + + // PRIORITIES + + addUnitPriority('week', 5); + addUnitPriority('isoWeek', 5); + + // PARSING + + addRegexToken('w', match1to2); + addRegexToken('ww', match1to2, match2); + addRegexToken('W', match1to2); + addRegexToken('WW', match1to2, match2); + + addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) { + week[token.substr(0, 1)] = toInt(input); + }); + + // HELPERS + + // LOCALES + + function localeWeek (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; + } + + var defaultLocaleWeek = { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + }; + + function localeFirstDayOfWeek () { + return this._week.dow; + } + + function localeFirstDayOfYear () { + return this._week.doy; + } + + // MOMENTS + + function getSetWeek (input) { + var week = this.localeData().week(this); + return input == null ? week : this.add((input - week) * 7, 'd'); + } + + function getSetISOWeek (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add((input - week) * 7, 'd'); + } + + // FORMATTING + + addFormatToken('d', 0, 'do', 'day'); + + addFormatToken('dd', 0, 0, function (format) { + return this.localeData().weekdaysMin(this, format); + }); + + addFormatToken('ddd', 0, 0, function (format) { + return this.localeData().weekdaysShort(this, format); + }); + + addFormatToken('dddd', 0, 0, function (format) { + return this.localeData().weekdays(this, format); + }); + + addFormatToken('e', 0, 0, 'weekday'); + addFormatToken('E', 0, 0, 'isoWeekday'); + + // ALIASES + + addUnitAlias('day', 'd'); + addUnitAlias('weekday', 'e'); + addUnitAlias('isoWeekday', 'E'); + + // PRIORITY + addUnitPriority('day', 11); + addUnitPriority('weekday', 11); + addUnitPriority('isoWeekday', 11); + + // PARSING + + addRegexToken('d', match1to2); + addRegexToken('e', match1to2); + addRegexToken('E', match1to2); + addRegexToken('dd', function (isStrict, locale) { + return locale.weekdaysMinRegex(isStrict); + }); + addRegexToken('ddd', function (isStrict, locale) { + return locale.weekdaysShortRegex(isStrict); + }); + addRegexToken('dddd', function (isStrict, locale) { + return locale.weekdaysRegex(isStrict); + }); + + addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) { + var weekday = config._locale.weekdaysParse(input, token, config._strict); + // if we didn't get a weekday name, mark the date as invalid + if (weekday != null) { + week.d = weekday; + } else { + getParsingFlags(config).invalidWeekday = input; + } + }); + + addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) { + week[token] = toInt(input); + }); + + // HELPERS + + function parseWeekday(input, locale) { + if (typeof input !== 'string') { + return input; + } + + if (!isNaN(input)) { + return parseInt(input, 10); + } + + input = locale.weekdaysParse(input); + if (typeof input === 'number') { + return input; + } + + return null; + } + + function parseIsoWeekday(input, locale) { + if (typeof input === 'string') { + return locale.weekdaysParse(input) % 7 || 7; + } + return isNaN(input) ? null : input; + } + + // LOCALES + + var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'); + function localeWeekdays (m, format) { + return isArray(this._weekdays) ? this._weekdays[m.day()] : + this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()]; + } + + var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'); + function localeWeekdaysShort (m) { + return this._weekdaysShort[m.day()]; + } + + var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'); + function localeWeekdaysMin (m) { + return this._weekdaysMin[m.day()]; + } + + function day_of_week__handleStrictParse(weekdayName, format, strict) { + var i, ii, mom, llc = weekdayName.toLocaleLowerCase(); + if (!this._weekdaysParse) { + this._weekdaysParse = []; + this._shortWeekdaysParse = []; + this._minWeekdaysParse = []; + + for (i = 0; i < 7; ++i) { + mom = create_utc__createUTC([2000, 1]).day(i); + this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase(); + this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase(); + this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase(); + } + } + + if (strict) { + if (format === 'dddd') { + ii = indexOf.call(this._weekdaysParse, llc); + return ii !== -1 ? ii : null; + } else if (format === 'ddd') { + ii = indexOf.call(this._shortWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } + } else { + if (format === 'dddd') { + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else if (format === 'ddd') { + ii = indexOf.call(this._shortWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._minWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } + } + } + + function localeWeekdaysParse (weekdayName, format, strict) { + var i, mom, regex; + + if (this._weekdaysParseExact) { + return day_of_week__handleStrictParse.call(this, weekdayName, format, strict); + } + + if (!this._weekdaysParse) { + this._weekdaysParse = []; + this._minWeekdaysParse = []; + this._shortWeekdaysParse = []; + this._fullWeekdaysParse = []; + } + + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + + mom = create_utc__createUTC([2000, 1]).day(i); + if (strict && !this._fullWeekdaysParse[i]) { + this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i'); + this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i'); + this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i'); + } + if (!this._weekdaysParse[i]) { + regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); + this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (!strict && this._weekdaysParse[i].test(weekdayName)) { + return i; + } + } + } + + // MOMENTS + + function getSetDayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + input = parseWeekday(input, this.localeData()); + return this.add(input - day, 'd'); + } else { + return day; + } + } + + function getSetLocaleDayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; + return input == null ? weekday : this.add(input - weekday, 'd'); + } + + function getSetISODayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + + // behaves the same as moment#day except + // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) + // as a setter, sunday should belong to the previous week. + + if (input != null) { + var weekday = parseIsoWeekday(input, this.localeData()); + return this.day(this.day() % 7 ? weekday : weekday - 7); + } else { + return this.day() || 7; + } + } + + var defaultWeekdaysRegex = matchWord; + function weekdaysRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysStrictRegex; + } else { + return this._weekdaysRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysRegex')) { + this._weekdaysRegex = defaultWeekdaysRegex; + } + return this._weekdaysStrictRegex && isStrict ? + this._weekdaysStrictRegex : this._weekdaysRegex; + } + } + + var defaultWeekdaysShortRegex = matchWord; + function weekdaysShortRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysShortStrictRegex; + } else { + return this._weekdaysShortRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysShortRegex')) { + this._weekdaysShortRegex = defaultWeekdaysShortRegex; + } + return this._weekdaysShortStrictRegex && isStrict ? + this._weekdaysShortStrictRegex : this._weekdaysShortRegex; + } + } + + var defaultWeekdaysMinRegex = matchWord; + function weekdaysMinRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysMinStrictRegex; + } else { + return this._weekdaysMinRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysMinRegex')) { + this._weekdaysMinRegex = defaultWeekdaysMinRegex; + } + return this._weekdaysMinStrictRegex && isStrict ? + this._weekdaysMinStrictRegex : this._weekdaysMinRegex; + } + } + + + function computeWeekdaysParse () { + function cmpLenRev(a, b) { + return b.length - a.length; + } + + var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [], + i, mom, minp, shortp, longp; + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + mom = create_utc__createUTC([2000, 1]).day(i); + minp = this.weekdaysMin(mom, ''); + shortp = this.weekdaysShort(mom, ''); + longp = this.weekdays(mom, ''); + minPieces.push(minp); + shortPieces.push(shortp); + longPieces.push(longp); + mixedPieces.push(minp); + mixedPieces.push(shortp); + mixedPieces.push(longp); + } + // Sorting makes sure if one weekday (or abbr) is a prefix of another it + // will match the longer piece. + minPieces.sort(cmpLenRev); + shortPieces.sort(cmpLenRev); + longPieces.sort(cmpLenRev); + mixedPieces.sort(cmpLenRev); + for (i = 0; i < 7; i++) { + shortPieces[i] = regexEscape(shortPieces[i]); + longPieces[i] = regexEscape(longPieces[i]); + mixedPieces[i] = regexEscape(mixedPieces[i]); + } + + this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); + this._weekdaysShortRegex = this._weekdaysRegex; + this._weekdaysMinRegex = this._weekdaysRegex; + + this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); + this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); + this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i'); + } + + // FORMATTING + + function hFormat() { + return this.hours() % 12 || 12; + } + + function kFormat() { + return this.hours() || 24; + } + + addFormatToken('H', ['HH', 2], 0, 'hour'); + addFormatToken('h', ['hh', 2], 0, hFormat); + addFormatToken('k', ['kk', 2], 0, kFormat); + + addFormatToken('hmm', 0, 0, function () { + return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2); + }); + + addFormatToken('hmmss', 0, 0, function () { + return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) + + zeroFill(this.seconds(), 2); + }); + + addFormatToken('Hmm', 0, 0, function () { + return '' + this.hours() + zeroFill(this.minutes(), 2); + }); + + addFormatToken('Hmmss', 0, 0, function () { + return '' + this.hours() + zeroFill(this.minutes(), 2) + + zeroFill(this.seconds(), 2); + }); + + function meridiem (token, lowercase) { + addFormatToken(token, 0, 0, function () { + return this.localeData().meridiem(this.hours(), this.minutes(), lowercase); + }); + } + + meridiem('a', true); + meridiem('A', false); + + // ALIASES + + addUnitAlias('hour', 'h'); + + // PRIORITY + addUnitPriority('hour', 13); + + // PARSING + + function matchMeridiem (isStrict, locale) { + return locale._meridiemParse; + } + + addRegexToken('a', matchMeridiem); + addRegexToken('A', matchMeridiem); + addRegexToken('H', match1to2); + addRegexToken('h', match1to2); + addRegexToken('HH', match1to2, match2); + addRegexToken('hh', match1to2, match2); + + addRegexToken('hmm', match3to4); + addRegexToken('hmmss', match5to6); + addRegexToken('Hmm', match3to4); + addRegexToken('Hmmss', match5to6); + + addParseToken(['H', 'HH'], HOUR); + addParseToken(['a', 'A'], function (input, array, config) { + config._isPm = config._locale.isPM(input); + config._meridiem = input; + }); + addParseToken(['h', 'hh'], function (input, array, config) { + array[HOUR] = toInt(input); + getParsingFlags(config).bigHour = true; + }); + addParseToken('hmm', function (input, array, config) { + var pos = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos)); + array[MINUTE] = toInt(input.substr(pos)); + getParsingFlags(config).bigHour = true; + }); + addParseToken('hmmss', function (input, array, config) { + var pos1 = input.length - 4; + var pos2 = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos1)); + array[MINUTE] = toInt(input.substr(pos1, 2)); + array[SECOND] = toInt(input.substr(pos2)); + getParsingFlags(config).bigHour = true; + }); + addParseToken('Hmm', function (input, array, config) { + var pos = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos)); + array[MINUTE] = toInt(input.substr(pos)); + }); + addParseToken('Hmmss', function (input, array, config) { + var pos1 = input.length - 4; + var pos2 = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos1)); + array[MINUTE] = toInt(input.substr(pos1, 2)); + array[SECOND] = toInt(input.substr(pos2)); + }); + + // LOCALES + + function localeIsPM (input) { + // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays + // Using charAt should be more compatible. + return ((input + '').toLowerCase().charAt(0) === 'p'); + } + + var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i; + function localeMeridiem (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } + } + + + // MOMENTS + + // Setting the hour should keep the time, because the user explicitly + // specified which hour he wants. So trying to maintain the same hour (in + // a new timezone) makes sense. Adding/subtracting hours does not follow + // this rule. + var getSetHour = makeGetSet('Hours', true); + + var baseConfig = { + calendar: defaultCalendar, + longDateFormat: defaultLongDateFormat, + invalidDate: defaultInvalidDate, + ordinal: defaultOrdinal, + ordinalParse: defaultOrdinalParse, + relativeTime: defaultRelativeTime, + + months: defaultLocaleMonths, + monthsShort: defaultLocaleMonthsShort, + + week: defaultLocaleWeek, + + weekdays: defaultLocaleWeekdays, + weekdaysMin: defaultLocaleWeekdaysMin, + weekdaysShort: defaultLocaleWeekdaysShort, + + meridiemParse: defaultLocaleMeridiemParse + }; + + // internal storage for locale config files + var locales = {}; + var globalLocale; + + function normalizeLocale(key) { + return key ? key.toLowerCase().replace('_', '-') : key; + } + + // pick the locale from the array + // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each + // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root + function chooseLocale(names) { + var i = 0, j, next, locale, split; + + while (i < names.length) { + split = normalizeLocale(names[i]).split('-'); + j = split.length; + next = normalizeLocale(names[i + 1]); + next = next ? next.split('-') : null; + while (j > 0) { + locale = loadLocale(split.slice(0, j).join('-')); + if (locale) { + return locale; + } + if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { + //the next array item is better than a shallower substring of this one + break; + } + j--; + } + i++; + } + return null; + } + + function loadLocale(name) { + var oldLocale = null; + // TODO: Find a better way to register and load all the locales in Node + if (!locales[name] && (typeof module !== 'undefined') && + module && module.exports) { + try { + oldLocale = globalLocale._abbr; + require('./locale/' + name); + // because defineLocale currently also sets the global locale, we + // want to undo that for lazy loaded locales + locale_locales__getSetGlobalLocale(oldLocale); + } catch (e) { } + } + return locales[name]; + } + + // This function will load locale and then set the global locale. If + // no arguments are passed in, it will simply return the current global + // locale key. + function locale_locales__getSetGlobalLocale (key, values) { + var data; + if (key) { + if (isUndefined(values)) { + data = locale_locales__getLocale(key); + } + else { + data = defineLocale(key, values); + } + + if (data) { + // moment.duration._locale = moment._locale = data; + globalLocale = data; + } + } + + return globalLocale._abbr; + } + + function defineLocale (name, config) { + if (config !== null) { + var parentConfig = baseConfig; + config.abbr = name; + if (locales[name] != null) { + deprecateSimple('defineLocaleOverride', + 'use moment.updateLocale(localeName, config) to change ' + + 'an existing locale. moment.defineLocale(localeName, ' + + 'config) should only be used for creating a new locale ' + + 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.'); + parentConfig = locales[name]._config; + } else if (config.parentLocale != null) { + if (locales[config.parentLocale] != null) { + parentConfig = locales[config.parentLocale]._config; + } else { + // treat as if there is no base config + deprecateSimple('parentLocaleUndefined', + 'specified parentLocale is not defined yet. See http://momentjs.com/guides/#/warnings/parent-locale/'); + } + } + locales[name] = new Locale(mergeConfigs(parentConfig, config)); + + // backwards compat for now: also set the locale + locale_locales__getSetGlobalLocale(name); + + return locales[name]; + } else { + // useful for testing + delete locales[name]; + return null; + } + } + + function updateLocale(name, config) { + if (config != null) { + var locale, parentConfig = baseConfig; + // MERGE + if (locales[name] != null) { + parentConfig = locales[name]._config; + } + config = mergeConfigs(parentConfig, config); + locale = new Locale(config); + locale.parentLocale = locales[name]; + locales[name] = locale; + + // backwards compat for now: also set the locale + locale_locales__getSetGlobalLocale(name); + } else { + // pass null for config to unupdate, useful for tests + if (locales[name] != null) { + if (locales[name].parentLocale != null) { + locales[name] = locales[name].parentLocale; + } else if (locales[name] != null) { + delete locales[name]; + } + } + } + return locales[name]; + } + + // returns locale data + function locale_locales__getLocale (key) { + var locale; + + if (key && key._locale && key._locale._abbr) { + key = key._locale._abbr; + } + + if (!key) { + return globalLocale; + } + + if (!isArray(key)) { + //short-circuit everything else + locale = loadLocale(key); + if (locale) { + return locale; + } + key = [key]; + } + + return chooseLocale(key); + } + + function locale_locales__listLocales() { + return keys(locales); + } + + function checkOverflow (m) { + var overflow; + var a = m._a; + + if (a && getParsingFlags(m).overflow === -2) { + overflow = + a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : + a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : + a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR : + a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : + a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : + a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : + -1; + + if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } + if (getParsingFlags(m)._overflowWeeks && overflow === -1) { + overflow = WEEK; + } + if (getParsingFlags(m)._overflowWeekday && overflow === -1) { + overflow = WEEKDAY; + } + + getParsingFlags(m).overflow = overflow; + } + + return m; + } + + // iso 8601 regex + // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) + var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/; + var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/; + + var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/; + + var isoDates = [ + ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], + ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], + ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], + ['GGGG-[W]WW', /\d{4}-W\d\d/, false], + ['YYYY-DDD', /\d{4}-\d{3}/], + ['YYYY-MM', /\d{4}-\d\d/, false], + ['YYYYYYMMDD', /[+-]\d{10}/], + ['YYYYMMDD', /\d{8}/], + // YYYYMM is NOT allowed by the standard + ['GGGG[W]WWE', /\d{4}W\d{3}/], + ['GGGG[W]WW', /\d{4}W\d{2}/, false], + ['YYYYDDD', /\d{7}/] + ]; + + // iso time formats and regexes + var isoTimes = [ + ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], + ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], + ['HH:mm:ss', /\d\d:\d\d:\d\d/], + ['HH:mm', /\d\d:\d\d/], + ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], + ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], + ['HHmmss', /\d\d\d\d\d\d/], + ['HHmm', /\d\d\d\d/], + ['HH', /\d\d/] + ]; + + var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; + + // date from iso format + function configFromISO(config) { + var i, l, + string = config._i, + match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string), + allowTime, dateFormat, timeFormat, tzFormat; + + if (match) { + getParsingFlags(config).iso = true; + + for (i = 0, l = isoDates.length; i < l; i++) { + if (isoDates[i][1].exec(match[1])) { + dateFormat = isoDates[i][0]; + allowTime = isoDates[i][2] !== false; + break; + } + } + if (dateFormat == null) { + config._isValid = false; + return; + } + if (match[3]) { + for (i = 0, l = isoTimes.length; i < l; i++) { + if (isoTimes[i][1].exec(match[3])) { + // match[2] should be 'T' or space + timeFormat = (match[2] || ' ') + isoTimes[i][0]; + break; + } + } + if (timeFormat == null) { + config._isValid = false; + return; + } + } + if (!allowTime && timeFormat != null) { + config._isValid = false; + return; + } + if (match[4]) { + if (tzRegex.exec(match[4])) { + tzFormat = 'Z'; + } else { + config._isValid = false; + return; + } + } + config._f = dateFormat + (timeFormat || '') + (tzFormat || ''); + configFromStringAndFormat(config); + } else { + config._isValid = false; + } + } + + // date from iso format or fallback + function configFromString(config) { + var matched = aspNetJsonRegex.exec(config._i); + + if (matched !== null) { + config._d = new Date(+matched[1]); + return; + } + + configFromISO(config); + if (config._isValid === false) { + delete config._isValid; + utils_hooks__hooks.createFromInputFallback(config); + } + } + + utils_hooks__hooks.createFromInputFallback = deprecate( + 'moment construction falls back to js Date. This is ' + + 'discouraged and will be removed in upcoming major ' + + 'release. Please refer to ' + + 'http://momentjs.com/guides/#/warnings/js-date/ for more info.', + function (config) { + config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); + } + ); + + // Pick the first defined of two or three arguments. + function defaults(a, b, c) { + if (a != null) { + return a; + } + if (b != null) { + return b; + } + return c; + } + + function currentDateArray(config) { + // hooks is actually the exported moment object + var nowValue = new Date(utils_hooks__hooks.now()); + if (config._useUTC) { + return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()]; + } + return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()]; + } + + // convert an array to a date. + // the array should mirror the parameters below + // note: all values past the year are optional and will default to the lowest possible value. + // [year, month, day , hour, minute, second, millisecond] + function configFromArray (config) { + var i, date, input = [], currentDate, yearToUse; + + if (config._d) { + return; + } + + currentDate = currentDateArray(config); + + //compute day of the year from weeks and weekdays + if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { + dayOfYearFromWeekInfo(config); + } + + //if the day of the year is set, figure out what it is + if (config._dayOfYear) { + yearToUse = defaults(config._a[YEAR], currentDate[YEAR]); + + if (config._dayOfYear > daysInYear(yearToUse)) { + getParsingFlags(config)._overflowDayOfYear = true; + } + + date = createUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); + } + + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } + + // Zero out whatever was not defaulted, including time + for (; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } + + // Check for 24:00:00.000 + if (config._a[HOUR] === 24 && + config._a[MINUTE] === 0 && + config._a[SECOND] === 0 && + config._a[MILLISECOND] === 0) { + config._nextDay = true; + config._a[HOUR] = 0; + } + + config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input); + // Apply timezone offset from input. The actual utcOffset can be changed + // with parseZone. + if (config._tzm != null) { + config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); + } + + if (config._nextDay) { + config._a[HOUR] = 24; + } + } + + function dayOfYearFromWeekInfo(config) { + var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow; + + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + dow = 1; + doy = 4; + + // TODO: We need to take the current isoWeekYear, but that depends on + // how we interpret now (local, utc, fixed offset). So create + // a now version of current config (take local/utc/offset flags, and + // create now). + weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year); + week = defaults(w.W, 1); + weekday = defaults(w.E, 1); + if (weekday < 1 || weekday > 7) { + weekdayOverflow = true; + } + } else { + dow = config._locale._week.dow; + doy = config._locale._week.doy; + + weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year); + week = defaults(w.w, 1); + + if (w.d != null) { + // weekday -- low day numbers are considered next week + weekday = w.d; + if (weekday < 0 || weekday > 6) { + weekdayOverflow = true; + } + } else if (w.e != null) { + // local weekday -- counting starts from begining of week + weekday = w.e + dow; + if (w.e < 0 || w.e > 6) { + weekdayOverflow = true; + } + } else { + // default to begining of week + weekday = dow; + } + } + if (week < 1 || week > weeksInYear(weekYear, dow, doy)) { + getParsingFlags(config)._overflowWeeks = true; + } else if (weekdayOverflow != null) { + getParsingFlags(config)._overflowWeekday = true; + } else { + temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy); + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; + } + } + + // constant that refers to the ISO standard + utils_hooks__hooks.ISO_8601 = function () {}; + + // date from string and format string + function configFromStringAndFormat(config) { + // TODO: Move this to another part of the creation flow to prevent circular deps + if (config._f === utils_hooks__hooks.ISO_8601) { + configFromISO(config); + return; + } + + config._a = []; + getParsingFlags(config).empty = true; + + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var string = '' + config._i, + i, parsedInput, tokens, token, skipped, + stringLength = string.length, + totalParsedInputLength = 0; + + tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; + + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; + // console.log('token', token, 'parsedInput', parsedInput, + // 'regex', getParseRegexForToken(token, config)); + if (parsedInput) { + skipped = string.substr(0, string.indexOf(parsedInput)); + if (skipped.length > 0) { + getParsingFlags(config).unusedInput.push(skipped); + } + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); + totalParsedInputLength += parsedInput.length; + } + // don't parse if it's not a known token + if (formatTokenFunctions[token]) { + if (parsedInput) { + getParsingFlags(config).empty = false; + } + else { + getParsingFlags(config).unusedTokens.push(token); + } + addTimeToArrayFromToken(token, parsedInput, config); + } + else if (config._strict && !parsedInput) { + getParsingFlags(config).unusedTokens.push(token); + } + } + + // add remaining unparsed input length to the string + getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + getParsingFlags(config).unusedInput.push(string); + } + + // clear _12h flag if hour is <= 12 + if (config._a[HOUR] <= 12 && + getParsingFlags(config).bigHour === true && + config._a[HOUR] > 0) { + getParsingFlags(config).bigHour = undefined; + } + + getParsingFlags(config).parsedDateParts = config._a.slice(0); + getParsingFlags(config).meridiem = config._meridiem; + // handle meridiem + config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem); + + configFromArray(config); + checkOverflow(config); + } + + + function meridiemFixWrap (locale, hour, meridiem) { + var isPm; + + if (meridiem == null) { + // nothing to do + return hour; + } + if (locale.meridiemHour != null) { + return locale.meridiemHour(hour, meridiem); + } else if (locale.isPM != null) { + // Fallback + isPm = locale.isPM(meridiem); + if (isPm && hour < 12) { + hour += 12; + } + if (!isPm && hour === 12) { + hour = 0; + } + return hour; + } else { + // this is not supposed to happen + return hour; + } + } + + // date from string and array of format strings + function configFromStringAndArray(config) { + var tempConfig, + bestMoment, + + scoreToBeat, + i, + currentScore; + + if (config._f.length === 0) { + getParsingFlags(config).invalidFormat = true; + config._d = new Date(NaN); + return; + } + + for (i = 0; i < config._f.length; i++) { + currentScore = 0; + tempConfig = copyConfig({}, config); + if (config._useUTC != null) { + tempConfig._useUTC = config._useUTC; + } + tempConfig._f = config._f[i]; + configFromStringAndFormat(tempConfig); + + if (!valid__isValid(tempConfig)) { + continue; + } + + // if there is any input that was not parsed add a penalty for that format + currentScore += getParsingFlags(tempConfig).charsLeftOver; + + //or tokens + currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10; + + getParsingFlags(tempConfig).score = currentScore; + + if (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } + } + + extend(config, bestMoment || tempConfig); + } + + function configFromObject(config) { + if (config._d) { + return; + } + + var i = normalizeObjectUnits(config._i); + config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) { + return obj && parseInt(obj, 10); + }); + + configFromArray(config); + } + + function createFromConfig (config) { + var res = new Moment(checkOverflow(prepareConfig(config))); + if (res._nextDay) { + // Adding is smart enough around DST + res.add(1, 'd'); + res._nextDay = undefined; + } + + return res; + } + + function prepareConfig (config) { + var input = config._i, + format = config._f; + + config._locale = config._locale || locale_locales__getLocale(config._l); + + if (input === null || (format === undefined && input === '')) { + return valid__createInvalid({nullInput: true}); + } + + if (typeof input === 'string') { + config._i = input = config._locale.preparse(input); + } + + if (isMoment(input)) { + return new Moment(checkOverflow(input)); + } else if (isArray(format)) { + configFromStringAndArray(config); + } else if (isDate(input)) { + config._d = input; + } else if (format) { + configFromStringAndFormat(config); + } else { + configFromInput(config); + } + + if (!valid__isValid(config)) { + config._d = null; + } + + return config; + } + + function configFromInput(config) { + var input = config._i; + if (input === undefined) { + config._d = new Date(utils_hooks__hooks.now()); + } else if (isDate(input)) { + config._d = new Date(input.valueOf()); + } else if (typeof input === 'string') { + configFromString(config); + } else if (isArray(input)) { + config._a = map(input.slice(0), function (obj) { + return parseInt(obj, 10); + }); + configFromArray(config); + } else if (typeof(input) === 'object') { + configFromObject(config); + } else if (typeof(input) === 'number') { + // from milliseconds + config._d = new Date(input); + } else { + utils_hooks__hooks.createFromInputFallback(config); + } + } + + function createLocalOrUTC (input, format, locale, strict, isUTC) { + var c = {}; + + if (typeof(locale) === 'boolean') { + strict = locale; + locale = undefined; + } + + if ((isObject(input) && isObjectEmpty(input)) || + (isArray(input) && input.length === 0)) { + input = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c._isAMomentObject = true; + c._useUTC = c._isUTC = isUTC; + c._l = locale; + c._i = input; + c._f = format; + c._strict = strict; + + return createFromConfig(c); + } + + function local__createLocal (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, false); + } + + var prototypeMin = deprecate( + 'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/', + function () { + var other = local__createLocal.apply(null, arguments); + if (this.isValid() && other.isValid()) { + return other < this ? this : other; + } else { + return valid__createInvalid(); + } + } + ); + + var prototypeMax = deprecate( + 'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/', + function () { + var other = local__createLocal.apply(null, arguments); + if (this.isValid() && other.isValid()) { + return other > this ? this : other; + } else { + return valid__createInvalid(); + } + } + ); + + // Pick a moment m from moments so that m[fn](other) is true for all + // other. This relies on the function fn to be transitive. + // + // moments should either be an array of moment objects or an array, whose + // first element is an array of moment objects. + function pickBy(fn, moments) { + var res, i; + if (moments.length === 1 && isArray(moments[0])) { + moments = moments[0]; + } + if (!moments.length) { + return local__createLocal(); + } + res = moments[0]; + for (i = 1; i < moments.length; ++i) { + if (!moments[i].isValid() || moments[i][fn](res)) { + res = moments[i]; + } + } + return res; + } + + // TODO: Use [].sort instead? + function min () { + var args = [].slice.call(arguments, 0); + + return pickBy('isBefore', args); + } + + function max () { + var args = [].slice.call(arguments, 0); + + return pickBy('isAfter', args); + } + + var now = function () { + return Date.now ? Date.now() : +(new Date()); + }; + + function Duration (duration) { + var normalizedInput = normalizeObjectUnits(duration), + years = normalizedInput.year || 0, + quarters = normalizedInput.quarter || 0, + months = normalizedInput.month || 0, + weeks = normalizedInput.week || 0, + days = normalizedInput.day || 0, + hours = normalizedInput.hour || 0, + minutes = normalizedInput.minute || 0, + seconds = normalizedInput.second || 0, + milliseconds = normalizedInput.millisecond || 0; + + // representation for dateAddRemove + this._milliseconds = +milliseconds + + seconds * 1e3 + // 1000 + minutes * 6e4 + // 1000 * 60 + hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978 + // Because of dateAddRemove treats 24 hours as different from a + // day when working around DST, we need to store them separately + this._days = +days + + weeks * 7; + // It is impossible translate months into days without knowing + // which months you are are talking about, so we have to store + // it separately. + this._months = +months + + quarters * 3 + + years * 12; + + this._data = {}; + + this._locale = locale_locales__getLocale(); + + this._bubble(); + } + + function isDuration (obj) { + return obj instanceof Duration; + } + + // FORMATTING + + function offset (token, separator) { + addFormatToken(token, 0, 0, function () { + var offset = this.utcOffset(); + var sign = '+'; + if (offset < 0) { + offset = -offset; + sign = '-'; + } + return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2); + }); + } + + offset('Z', ':'); + offset('ZZ', ''); + + // PARSING + + addRegexToken('Z', matchShortOffset); + addRegexToken('ZZ', matchShortOffset); + addParseToken(['Z', 'ZZ'], function (input, array, config) { + config._useUTC = true; + config._tzm = offsetFromString(matchShortOffset, input); + }); + + // HELPERS + + // timezone chunker + // '+10:00' > ['10', '00'] + // '-1530' > ['-15', '30'] + var chunkOffset = /([\+\-]|\d\d)/gi; + + function offsetFromString(matcher, string) { + var matches = ((string || '').match(matcher) || []); + var chunk = matches[matches.length - 1] || []; + var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0]; + var minutes = +(parts[1] * 60) + toInt(parts[2]); + + return parts[0] === '+' ? minutes : -minutes; + } + + // Return a moment from input, that is local/utc/zone equivalent to model. + function cloneWithOffset(input, model) { + var res, diff; + if (model._isUTC) { + res = model.clone(); + diff = (isMoment(input) || isDate(input) ? input.valueOf() : local__createLocal(input).valueOf()) - res.valueOf(); + // Use low-level api, because this fn is low-level api. + res._d.setTime(res._d.valueOf() + diff); + utils_hooks__hooks.updateOffset(res, false); + return res; + } else { + return local__createLocal(input).local(); + } + } + + function getDateOffset (m) { + // On Firefox.24 Date#getTimezoneOffset returns a floating point. + // https://github.com/moment/moment/pull/1871 + return -Math.round(m._d.getTimezoneOffset() / 15) * 15; + } + + // HOOKS + + // This function will be called whenever a moment is mutated. + // It is intended to keep the offset in sync with the timezone. + utils_hooks__hooks.updateOffset = function () {}; + + // MOMENTS + + // keepLocalTime = true means only change the timezone, without + // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> + // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset + // +0200, so we adjust the time as needed, to be valid. + // + // Keeping the time actually adds/subtracts (one hour) + // from the actual represented time. That is why we call updateOffset + // a second time. In case it wants us to change the offset again + // _changeInProgress == true case, then we have to adjust, because + // there is no such time in the given timezone. + function getSetOffset (input, keepLocalTime) { + var offset = this._offset || 0, + localAdjust; + if (!this.isValid()) { + return input != null ? this : NaN; + } + if (input != null) { + if (typeof input === 'string') { + input = offsetFromString(matchShortOffset, input); + } else if (Math.abs(input) < 16) { + input = input * 60; + } + if (!this._isUTC && keepLocalTime) { + localAdjust = getDateOffset(this); + } + this._offset = input; + this._isUTC = true; + if (localAdjust != null) { + this.add(localAdjust, 'm'); + } + if (offset !== input) { + if (!keepLocalTime || this._changeInProgress) { + add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false); + } else if (!this._changeInProgress) { + this._changeInProgress = true; + utils_hooks__hooks.updateOffset(this, true); + this._changeInProgress = null; + } + } + return this; + } else { + return this._isUTC ? offset : getDateOffset(this); + } + } + + function getSetZone (input, keepLocalTime) { + if (input != null) { + if (typeof input !== 'string') { + input = -input; + } + + this.utcOffset(input, keepLocalTime); + + return this; + } else { + return -this.utcOffset(); + } + } + + function setOffsetToUTC (keepLocalTime) { + return this.utcOffset(0, keepLocalTime); + } + + function setOffsetToLocal (keepLocalTime) { + if (this._isUTC) { + this.utcOffset(0, keepLocalTime); + this._isUTC = false; + + if (keepLocalTime) { + this.subtract(getDateOffset(this), 'm'); + } + } + return this; + } + + function setOffsetToParsedOffset () { + if (this._tzm) { + this.utcOffset(this._tzm); + } else if (typeof this._i === 'string') { + this.utcOffset(offsetFromString(matchOffset, this._i)); + } + return this; + } + + function hasAlignedHourOffset (input) { + if (!this.isValid()) { + return false; + } + input = input ? local__createLocal(input).utcOffset() : 0; + + return (this.utcOffset() - input) % 60 === 0; + } + + function isDaylightSavingTime () { + return ( + this.utcOffset() > this.clone().month(0).utcOffset() || + this.utcOffset() > this.clone().month(5).utcOffset() + ); + } + + function isDaylightSavingTimeShifted () { + if (!isUndefined(this._isDSTShifted)) { + return this._isDSTShifted; + } + + var c = {}; + + copyConfig(c, this); + c = prepareConfig(c); + + if (c._a) { + var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a); + this._isDSTShifted = this.isValid() && + compareArrays(c._a, other.toArray()) > 0; + } else { + this._isDSTShifted = false; + } + + return this._isDSTShifted; + } + + function isLocal () { + return this.isValid() ? !this._isUTC : false; + } + + function isUtcOffset () { + return this.isValid() ? this._isUTC : false; + } + + function isUtc () { + return this.isValid() ? this._isUTC && this._offset === 0 : false; + } + + // ASP.NET json date format regex + var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/; + + // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html + // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere + // and further modified to allow for strings containing both week and day + var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/; + + function create__createDuration (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + diffRes; + + if (isDuration(input)) { + duration = { + ms : input._milliseconds, + d : input._days, + M : input._months + }; + } else if (typeof input === 'number') { + duration = {}; + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (!!(match = aspNetRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : 0, + d : toInt(match[DATE]) * sign, + h : toInt(match[HOUR]) * sign, + m : toInt(match[MINUTE]) * sign, + s : toInt(match[SECOND]) * sign, + ms : toInt(match[MILLISECOND]) * sign + }; + } else if (!!(match = isoRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : parseIso(match[2], sign), + M : parseIso(match[3], sign), + w : parseIso(match[4], sign), + d : parseIso(match[5], sign), + h : parseIso(match[6], sign), + m : parseIso(match[7], sign), + s : parseIso(match[8], sign) + }; + } else if (duration == null) {// checks for null or undefined + duration = {}; + } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) { + diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to)); + + duration = {}; + duration.ms = diffRes.milliseconds; + duration.M = diffRes.months; + } + + ret = new Duration(duration); + + if (isDuration(input) && hasOwnProp(input, '_locale')) { + ret._locale = input._locale; + } + + return ret; + } + + create__createDuration.fn = Duration.prototype; + + function parseIso (inp, sign) { + // We'd normally use ~~inp for this, but unfortunately it also + // converts floats to ints. + // inp may be undefined, so careful calling replace on it. + var res = inp && parseFloat(inp.replace(',', '.')); + // apply sign while we're at it + return (isNaN(res) ? 0 : res) * sign; + } + + function positiveMomentsDifference(base, other) { + var res = {milliseconds: 0, months: 0}; + + res.months = other.month() - base.month() + + (other.year() - base.year()) * 12; + if (base.clone().add(res.months, 'M').isAfter(other)) { + --res.months; + } + + res.milliseconds = +other - +(base.clone().add(res.months, 'M')); + + return res; + } + + function momentsDifference(base, other) { + var res; + if (!(base.isValid() && other.isValid())) { + return {milliseconds: 0, months: 0}; + } + + other = cloneWithOffset(other, base); + if (base.isBefore(other)) { + res = positiveMomentsDifference(base, other); + } else { + res = positiveMomentsDifference(other, base); + res.milliseconds = -res.milliseconds; + res.months = -res.months; + } + + return res; + } + + function absRound (number) { + if (number < 0) { + return Math.round(-1 * number) * -1; + } else { + return Math.round(number); + } + } + + // TODO: remove 'name' arg after deprecation is removed + function createAdder(direction, name) { + return function (val, period) { + var dur, tmp; + //invert the arguments, but complain about it + if (period !== null && !isNaN(+period)) { + deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' + + 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.'); + tmp = val; val = period; period = tmp; + } + + val = typeof val === 'string' ? +val : val; + dur = create__createDuration(val, period); + add_subtract__addSubtract(this, dur, direction); + return this; + }; + } + + function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) { + var milliseconds = duration._milliseconds, + days = absRound(duration._days), + months = absRound(duration._months); + + if (!mom.isValid()) { + // No op + return; + } + + updateOffset = updateOffset == null ? true : updateOffset; + + if (milliseconds) { + mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding); + } + if (days) { + get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding); + } + if (months) { + setMonth(mom, get_set__get(mom, 'Month') + months * isAdding); + } + if (updateOffset) { + utils_hooks__hooks.updateOffset(mom, days || months); + } + } + + var add_subtract__add = createAdder(1, 'add'); + var add_subtract__subtract = createAdder(-1, 'subtract'); + + function getCalendarFormat(myMoment, now) { + var diff = myMoment.diff(now, 'days', true); + return diff < -6 ? 'sameElse' : + diff < -1 ? 'lastWeek' : + diff < 0 ? 'lastDay' : + diff < 1 ? 'sameDay' : + diff < 2 ? 'nextDay' : + diff < 7 ? 'nextWeek' : 'sameElse'; + } + + function moment_calendar__calendar (time, formats) { + // We want to compare the start of today, vs this. + // Getting start-of-today depends on whether we're local/utc/offset or not. + var now = time || local__createLocal(), + sod = cloneWithOffset(now, this).startOf('day'), + format = utils_hooks__hooks.calendarFormat(this, sod) || 'sameElse'; + + var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]); + + return this.format(output || this.localeData().calendar(format, this, local__createLocal(now))); + } + + function clone () { + return new Moment(this); + } + + function isAfter (input, units) { + var localInput = isMoment(input) ? input : local__createLocal(input); + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(!isUndefined(units) ? units : 'millisecond'); + if (units === 'millisecond') { + return this.valueOf() > localInput.valueOf(); + } else { + return localInput.valueOf() < this.clone().startOf(units).valueOf(); + } + } + + function isBefore (input, units) { + var localInput = isMoment(input) ? input : local__createLocal(input); + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(!isUndefined(units) ? units : 'millisecond'); + if (units === 'millisecond') { + return this.valueOf() < localInput.valueOf(); + } else { + return this.clone().endOf(units).valueOf() < localInput.valueOf(); + } + } + + function isBetween (from, to, units, inclusivity) { + inclusivity = inclusivity || '()'; + return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) && + (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units)); + } + + function isSame (input, units) { + var localInput = isMoment(input) ? input : local__createLocal(input), + inputMs; + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(units || 'millisecond'); + if (units === 'millisecond') { + return this.valueOf() === localInput.valueOf(); + } else { + inputMs = localInput.valueOf(); + return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf(); + } + } + + function isSameOrAfter (input, units) { + return this.isSame(input, units) || this.isAfter(input,units); + } + + function isSameOrBefore (input, units) { + return this.isSame(input, units) || this.isBefore(input,units); + } + + function diff (input, units, asFloat) { + var that, + zoneDelta, + delta, output; + + if (!this.isValid()) { + return NaN; + } + + that = cloneWithOffset(input, this); + + if (!that.isValid()) { + return NaN; + } + + zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4; + + units = normalizeUnits(units); + + if (units === 'year' || units === 'month' || units === 'quarter') { + output = monthDiff(this, that); + if (units === 'quarter') { + output = output / 3; + } else if (units === 'year') { + output = output / 12; + } + } else { + delta = this - that; + output = units === 'second' ? delta / 1e3 : // 1000 + units === 'minute' ? delta / 6e4 : // 1000 * 60 + units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60 + units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst + units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst + delta; + } + return asFloat ? output : absFloor(output); + } + + function monthDiff (a, b) { + // difference in months + var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()), + // b is in (anchor - 1 month, anchor + 1 month) + anchor = a.clone().add(wholeMonthDiff, 'months'), + anchor2, adjust; + + if (b - anchor < 0) { + anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor - anchor2); + } else { + anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor2 - anchor); + } + + //check for negative zero, return zero if negative zero + return -(wholeMonthDiff + adjust) || 0; + } + + utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ'; + utils_hooks__hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]'; + + function toString () { + return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); + } + + function moment_format__toISOString () { + var m = this.clone().utc(); + if (0 < m.year() && m.year() <= 9999) { + if (isFunction(Date.prototype.toISOString)) { + // native implementation is ~50x faster, use it when we can + return this.toDate().toISOString(); + } else { + return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + } else { + return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + } + + function format (inputString) { + if (!inputString) { + inputString = this.isUtc() ? utils_hooks__hooks.defaultFormatUtc : utils_hooks__hooks.defaultFormat; + } + var output = formatMoment(this, inputString); + return this.localeData().postformat(output); + } + + function from (time, withoutSuffix) { + if (this.isValid() && + ((isMoment(time) && time.isValid()) || + local__createLocal(time).isValid())) { + return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); + } else { + return this.localeData().invalidDate(); + } + } + + function fromNow (withoutSuffix) { + return this.from(local__createLocal(), withoutSuffix); + } + + function to (time, withoutSuffix) { + if (this.isValid() && + ((isMoment(time) && time.isValid()) || + local__createLocal(time).isValid())) { + return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix); + } else { + return this.localeData().invalidDate(); + } + } + + function toNow (withoutSuffix) { + return this.to(local__createLocal(), withoutSuffix); + } + + // If passed a locale key, it will set the locale for this + // instance. Otherwise, it will return the locale configuration + // variables for this instance. + function locale (key) { + var newLocaleData; + + if (key === undefined) { + return this._locale._abbr; + } else { + newLocaleData = locale_locales__getLocale(key); + if (newLocaleData != null) { + this._locale = newLocaleData; + } + return this; + } + } + + var lang = deprecate( + 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', + function (key) { + if (key === undefined) { + return this.localeData(); + } else { + return this.locale(key); + } + } + ); + + function localeData () { + return this._locale; + } + + function startOf (units) { + units = normalizeUnits(units); + // the following switch intentionally omits break keywords + // to utilize falling through the cases. + switch (units) { + case 'year': + this.month(0); + /* falls through */ + case 'quarter': + case 'month': + this.date(1); + /* falls through */ + case 'week': + case 'isoWeek': + case 'day': + case 'date': + this.hours(0); + /* falls through */ + case 'hour': + this.minutes(0); + /* falls through */ + case 'minute': + this.seconds(0); + /* falls through */ + case 'second': + this.milliseconds(0); + } + + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } + if (units === 'isoWeek') { + this.isoWeekday(1); + } + + // quarters are also special + if (units === 'quarter') { + this.month(Math.floor(this.month() / 3) * 3); + } + + return this; + } + + function endOf (units) { + units = normalizeUnits(units); + if (units === undefined || units === 'millisecond') { + return this; + } + + // 'date' is an alias for 'day', so it should be considered as such. + if (units === 'date') { + units = 'day'; + } + + return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); + } + + function to_type__valueOf () { + return this._d.valueOf() - ((this._offset || 0) * 60000); + } + + function unix () { + return Math.floor(this.valueOf() / 1000); + } + + function toDate () { + return new Date(this.valueOf()); + } + + function toArray () { + var m = this; + return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()]; + } + + function toObject () { + var m = this; + return { + years: m.year(), + months: m.month(), + date: m.date(), + hours: m.hours(), + minutes: m.minutes(), + seconds: m.seconds(), + milliseconds: m.milliseconds() + }; + } + + function toJSON () { + // new Date(NaN).toJSON() === null + return this.isValid() ? this.toISOString() : null; + } + + function moment_valid__isValid () { + return valid__isValid(this); + } + + function parsingFlags () { + return extend({}, getParsingFlags(this)); + } + + function invalidAt () { + return getParsingFlags(this).overflow; + } + + function creationData() { + return { + input: this._i, + format: this._f, + locale: this._locale, + isUTC: this._isUTC, + strict: this._strict + }; + } + + // FORMATTING + + addFormatToken(0, ['gg', 2], 0, function () { + return this.weekYear() % 100; + }); + + addFormatToken(0, ['GG', 2], 0, function () { + return this.isoWeekYear() % 100; + }); + + function addWeekYearFormatToken (token, getter) { + addFormatToken(0, [token, token.length], 0, getter); + } + + addWeekYearFormatToken('gggg', 'weekYear'); + addWeekYearFormatToken('ggggg', 'weekYear'); + addWeekYearFormatToken('GGGG', 'isoWeekYear'); + addWeekYearFormatToken('GGGGG', 'isoWeekYear'); + + // ALIASES + + addUnitAlias('weekYear', 'gg'); + addUnitAlias('isoWeekYear', 'GG'); + + // PRIORITY + + addUnitPriority('weekYear', 1); + addUnitPriority('isoWeekYear', 1); + + + // PARSING + + addRegexToken('G', matchSigned); + addRegexToken('g', matchSigned); + addRegexToken('GG', match1to2, match2); + addRegexToken('gg', match1to2, match2); + addRegexToken('GGGG', match1to4, match4); + addRegexToken('gggg', match1to4, match4); + addRegexToken('GGGGG', match1to6, match6); + addRegexToken('ggggg', match1to6, match6); + + addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) { + week[token.substr(0, 2)] = toInt(input); + }); + + addWeekParseToken(['gg', 'GG'], function (input, week, config, token) { + week[token] = utils_hooks__hooks.parseTwoDigitYear(input); + }); + + // MOMENTS + + function getSetWeekYear (input) { + return getSetWeekYearHelper.call(this, + input, + this.week(), + this.weekday(), + this.localeData()._week.dow, + this.localeData()._week.doy); + } + + function getSetISOWeekYear (input) { + return getSetWeekYearHelper.call(this, + input, this.isoWeek(), this.isoWeekday(), 1, 4); + } + + function getISOWeeksInYear () { + return weeksInYear(this.year(), 1, 4); + } + + function getWeeksInYear () { + var weekInfo = this.localeData()._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); + } + + function getSetWeekYearHelper(input, week, weekday, dow, doy) { + var weeksTarget; + if (input == null) { + return weekOfYear(this, dow, doy).year; + } else { + weeksTarget = weeksInYear(input, dow, doy); + if (week > weeksTarget) { + week = weeksTarget; + } + return setWeekAll.call(this, input, week, weekday, dow, doy); + } + } + + function setWeekAll(weekYear, week, weekday, dow, doy) { + var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy), + date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear); + + this.year(date.getUTCFullYear()); + this.month(date.getUTCMonth()); + this.date(date.getUTCDate()); + return this; + } + + // FORMATTING + + addFormatToken('Q', 0, 'Qo', 'quarter'); + + // ALIASES + + addUnitAlias('quarter', 'Q'); + + // PRIORITY + + addUnitPriority('quarter', 7); + + // PARSING + + addRegexToken('Q', match1); + addParseToken('Q', function (input, array) { + array[MONTH] = (toInt(input) - 1) * 3; + }); + + // MOMENTS + + function getSetQuarter (input) { + return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); + } + + // FORMATTING + + addFormatToken('D', ['DD', 2], 'Do', 'date'); + + // ALIASES + + addUnitAlias('date', 'D'); + + // PRIOROITY + addUnitPriority('date', 9); + + // PARSING + + addRegexToken('D', match1to2); + addRegexToken('DD', match1to2, match2); + addRegexToken('Do', function (isStrict, locale) { + return isStrict ? locale._ordinalParse : locale._ordinalParseLenient; + }); + + addParseToken(['D', 'DD'], DATE); + addParseToken('Do', function (input, array) { + array[DATE] = toInt(input.match(match1to2)[0], 10); + }); + + // MOMENTS + + var getSetDayOfMonth = makeGetSet('Date', true); + + // FORMATTING + + addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); + + // ALIASES + + addUnitAlias('dayOfYear', 'DDD'); + + // PRIORITY + addUnitPriority('dayOfYear', 4); + + // PARSING + + addRegexToken('DDD', match1to3); + addRegexToken('DDDD', match3); + addParseToken(['DDD', 'DDDD'], function (input, array, config) { + config._dayOfYear = toInt(input); + }); + + // HELPERS + + // MOMENTS + + function getSetDayOfYear (input) { + var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); + } + + // FORMATTING + + addFormatToken('m', ['mm', 2], 0, 'minute'); + + // ALIASES + + addUnitAlias('minute', 'm'); + + // PRIORITY + + addUnitPriority('minute', 14); + + // PARSING + + addRegexToken('m', match1to2); + addRegexToken('mm', match1to2, match2); + addParseToken(['m', 'mm'], MINUTE); + + // MOMENTS + + var getSetMinute = makeGetSet('Minutes', false); + + // FORMATTING + + addFormatToken('s', ['ss', 2], 0, 'second'); + + // ALIASES + + addUnitAlias('second', 's'); + + // PRIORITY + + addUnitPriority('second', 15); + + // PARSING + + addRegexToken('s', match1to2); + addRegexToken('ss', match1to2, match2); + addParseToken(['s', 'ss'], SECOND); + + // MOMENTS + + var getSetSecond = makeGetSet('Seconds', false); + + // FORMATTING + + addFormatToken('S', 0, 0, function () { + return ~~(this.millisecond() / 100); + }); + + addFormatToken(0, ['SS', 2], 0, function () { + return ~~(this.millisecond() / 10); + }); + + addFormatToken(0, ['SSS', 3], 0, 'millisecond'); + addFormatToken(0, ['SSSS', 4], 0, function () { + return this.millisecond() * 10; + }); + addFormatToken(0, ['SSSSS', 5], 0, function () { + return this.millisecond() * 100; + }); + addFormatToken(0, ['SSSSSS', 6], 0, function () { + return this.millisecond() * 1000; + }); + addFormatToken(0, ['SSSSSSS', 7], 0, function () { + return this.millisecond() * 10000; + }); + addFormatToken(0, ['SSSSSSSS', 8], 0, function () { + return this.millisecond() * 100000; + }); + addFormatToken(0, ['SSSSSSSSS', 9], 0, function () { + return this.millisecond() * 1000000; + }); + + + // ALIASES + + addUnitAlias('millisecond', 'ms'); + + // PRIORITY + + addUnitPriority('millisecond', 16); + + // PARSING + + addRegexToken('S', match1to3, match1); + addRegexToken('SS', match1to3, match2); + addRegexToken('SSS', match1to3, match3); + + var token; + for (token = 'SSSS'; token.length <= 9; token += 'S') { + addRegexToken(token, matchUnsigned); + } + + function parseMs(input, array) { + array[MILLISECOND] = toInt(('0.' + input) * 1000); + } + + for (token = 'S'; token.length <= 9; token += 'S') { + addParseToken(token, parseMs); + } + // MOMENTS + + var getSetMillisecond = makeGetSet('Milliseconds', false); + + // FORMATTING + + addFormatToken('z', 0, 0, 'zoneAbbr'); + addFormatToken('zz', 0, 0, 'zoneName'); + + // MOMENTS + + function getZoneAbbr () { + return this._isUTC ? 'UTC' : ''; + } + + function getZoneName () { + return this._isUTC ? 'Coordinated Universal Time' : ''; + } + + var momentPrototype__proto = Moment.prototype; + + momentPrototype__proto.add = add_subtract__add; + momentPrototype__proto.calendar = moment_calendar__calendar; + momentPrototype__proto.clone = clone; + momentPrototype__proto.diff = diff; + momentPrototype__proto.endOf = endOf; + momentPrototype__proto.format = format; + momentPrototype__proto.from = from; + momentPrototype__proto.fromNow = fromNow; + momentPrototype__proto.to = to; + momentPrototype__proto.toNow = toNow; + momentPrototype__proto.get = stringGet; + momentPrototype__proto.invalidAt = invalidAt; + momentPrototype__proto.isAfter = isAfter; + momentPrototype__proto.isBefore = isBefore; + momentPrototype__proto.isBetween = isBetween; + momentPrototype__proto.isSame = isSame; + momentPrototype__proto.isSameOrAfter = isSameOrAfter; + momentPrototype__proto.isSameOrBefore = isSameOrBefore; + momentPrototype__proto.isValid = moment_valid__isValid; + momentPrototype__proto.lang = lang; + momentPrototype__proto.locale = locale; + momentPrototype__proto.localeData = localeData; + momentPrototype__proto.max = prototypeMax; + momentPrototype__proto.min = prototypeMin; + momentPrototype__proto.parsingFlags = parsingFlags; + momentPrototype__proto.set = stringSet; + momentPrototype__proto.startOf = startOf; + momentPrototype__proto.subtract = add_subtract__subtract; + momentPrototype__proto.toArray = toArray; + momentPrototype__proto.toObject = toObject; + momentPrototype__proto.toDate = toDate; + momentPrototype__proto.toISOString = moment_format__toISOString; + momentPrototype__proto.toJSON = toJSON; + momentPrototype__proto.toString = toString; + momentPrototype__proto.unix = unix; + momentPrototype__proto.valueOf = to_type__valueOf; + momentPrototype__proto.creationData = creationData; + + // Year + momentPrototype__proto.year = getSetYear; + momentPrototype__proto.isLeapYear = getIsLeapYear; + + // Week Year + momentPrototype__proto.weekYear = getSetWeekYear; + momentPrototype__proto.isoWeekYear = getSetISOWeekYear; + + // Quarter + momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter; + + // Month + momentPrototype__proto.month = getSetMonth; + momentPrototype__proto.daysInMonth = getDaysInMonth; + + // Week + momentPrototype__proto.week = momentPrototype__proto.weeks = getSetWeek; + momentPrototype__proto.isoWeek = momentPrototype__proto.isoWeeks = getSetISOWeek; + momentPrototype__proto.weeksInYear = getWeeksInYear; + momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear; + + // Day + momentPrototype__proto.date = getSetDayOfMonth; + momentPrototype__proto.day = momentPrototype__proto.days = getSetDayOfWeek; + momentPrototype__proto.weekday = getSetLocaleDayOfWeek; + momentPrototype__proto.isoWeekday = getSetISODayOfWeek; + momentPrototype__proto.dayOfYear = getSetDayOfYear; + + // Hour + momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour; + + // Minute + momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute; + + // Second + momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond; + + // Millisecond + momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond; + + // Offset + momentPrototype__proto.utcOffset = getSetOffset; + momentPrototype__proto.utc = setOffsetToUTC; + momentPrototype__proto.local = setOffsetToLocal; + momentPrototype__proto.parseZone = setOffsetToParsedOffset; + momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset; + momentPrototype__proto.isDST = isDaylightSavingTime; + momentPrototype__proto.isLocal = isLocal; + momentPrototype__proto.isUtcOffset = isUtcOffset; + momentPrototype__proto.isUtc = isUtc; + momentPrototype__proto.isUTC = isUtc; + + // Timezone + momentPrototype__proto.zoneAbbr = getZoneAbbr; + momentPrototype__proto.zoneName = getZoneName; + + // Deprecations + momentPrototype__proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth); + momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth); + momentPrototype__proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear); + momentPrototype__proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone); + momentPrototype__proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted); + + var momentPrototype = momentPrototype__proto; + + function moment__createUnix (input) { + return local__createLocal(input * 1000); + } + + function moment__createInZone () { + return local__createLocal.apply(null, arguments).parseZone(); + } + + function preParsePostFormat (string) { + return string; + } + + var prototype__proto = Locale.prototype; + + prototype__proto.calendar = locale_calendar__calendar; + prototype__proto.longDateFormat = longDateFormat; + prototype__proto.invalidDate = invalidDate; + prototype__proto.ordinal = ordinal; + prototype__proto.preparse = preParsePostFormat; + prototype__proto.postformat = preParsePostFormat; + prototype__proto.relativeTime = relative__relativeTime; + prototype__proto.pastFuture = pastFuture; + prototype__proto.set = locale_set__set; + + // Month + prototype__proto.months = localeMonths; + prototype__proto.monthsShort = localeMonthsShort; + prototype__proto.monthsParse = localeMonthsParse; + prototype__proto.monthsRegex = monthsRegex; + prototype__proto.monthsShortRegex = monthsShortRegex; + + // Week + prototype__proto.week = localeWeek; + prototype__proto.firstDayOfYear = localeFirstDayOfYear; + prototype__proto.firstDayOfWeek = localeFirstDayOfWeek; + + // Day of Week + prototype__proto.weekdays = localeWeekdays; + prototype__proto.weekdaysMin = localeWeekdaysMin; + prototype__proto.weekdaysShort = localeWeekdaysShort; + prototype__proto.weekdaysParse = localeWeekdaysParse; + + prototype__proto.weekdaysRegex = weekdaysRegex; + prototype__proto.weekdaysShortRegex = weekdaysShortRegex; + prototype__proto.weekdaysMinRegex = weekdaysMinRegex; + + // Hours + prototype__proto.isPM = localeIsPM; + prototype__proto.meridiem = localeMeridiem; + + function lists__get (format, index, field, setter) { + var locale = locale_locales__getLocale(); + var utc = create_utc__createUTC().set(setter, index); + return locale[field](utc, format); + } + + function listMonthsImpl (format, index, field) { + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + + if (index != null) { + return lists__get(format, index, field, 'month'); + } + + var i; + var out = []; + for (i = 0; i < 12; i++) { + out[i] = lists__get(format, i, field, 'month'); + } + return out; + } + + // () + // (5) + // (fmt, 5) + // (fmt) + // (true) + // (true, 5) + // (true, fmt, 5) + // (true, fmt) + function listWeekdaysImpl (localeSorted, format, index, field) { + if (typeof localeSorted === 'boolean') { + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + } else { + format = localeSorted; + index = format; + localeSorted = false; + + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + } + + var locale = locale_locales__getLocale(), + shift = localeSorted ? locale._week.dow : 0; + + if (index != null) { + return lists__get(format, (index + shift) % 7, field, 'day'); + } + + var i; + var out = []; + for (i = 0; i < 7; i++) { + out[i] = lists__get(format, (i + shift) % 7, field, 'day'); + } + return out; + } + + function lists__listMonths (format, index) { + return listMonthsImpl(format, index, 'months'); + } + + function lists__listMonthsShort (format, index) { + return listMonthsImpl(format, index, 'monthsShort'); + } + + function lists__listWeekdays (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdays'); + } + + function lists__listWeekdaysShort (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort'); + } + + function lists__listWeekdaysMin (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin'); + } + + locale_locales__getSetGlobalLocale('en', { + ordinalParse: /\d{1,2}(th|st|nd|rd)/, + ordinal : function (number) { + var b = number % 10, + output = (toInt(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } + }); + + // Side effect imports + utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale); + utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale); + + var mathAbs = Math.abs; + + function duration_abs__abs () { + var data = this._data; + + this._milliseconds = mathAbs(this._milliseconds); + this._days = mathAbs(this._days); + this._months = mathAbs(this._months); + + data.milliseconds = mathAbs(data.milliseconds); + data.seconds = mathAbs(data.seconds); + data.minutes = mathAbs(data.minutes); + data.hours = mathAbs(data.hours); + data.months = mathAbs(data.months); + data.years = mathAbs(data.years); + + return this; + } + + function duration_add_subtract__addSubtract (duration, input, value, direction) { + var other = create__createDuration(input, value); + + duration._milliseconds += direction * other._milliseconds; + duration._days += direction * other._days; + duration._months += direction * other._months; + + return duration._bubble(); + } + + // supports only 2.0-style add(1, 's') or add(duration) + function duration_add_subtract__add (input, value) { + return duration_add_subtract__addSubtract(this, input, value, 1); + } + + // supports only 2.0-style subtract(1, 's') or subtract(duration) + function duration_add_subtract__subtract (input, value) { + return duration_add_subtract__addSubtract(this, input, value, -1); + } + + function absCeil (number) { + if (number < 0) { + return Math.floor(number); + } else { + return Math.ceil(number); + } + } + + function bubble () { + var milliseconds = this._milliseconds; + var days = this._days; + var months = this._months; + var data = this._data; + var seconds, minutes, hours, years, monthsFromDays; + + // if we have a mix of positive and negative values, bubble down first + // check: https://github.com/moment/moment/issues/2166 + if (!((milliseconds >= 0 && days >= 0 && months >= 0) || + (milliseconds <= 0 && days <= 0 && months <= 0))) { + milliseconds += absCeil(monthsToDays(months) + days) * 864e5; + days = 0; + months = 0; + } + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absFloor(milliseconds / 1000); + data.seconds = seconds % 60; + + minutes = absFloor(seconds / 60); + data.minutes = minutes % 60; + + hours = absFloor(minutes / 60); + data.hours = hours % 24; + + days += absFloor(hours / 24); + + // convert days to months + monthsFromDays = absFloor(daysToMonths(days)); + months += monthsFromDays; + days -= absCeil(monthsToDays(monthsFromDays)); + + // 12 months -> 1 year + years = absFloor(months / 12); + months %= 12; + + data.days = days; + data.months = months; + data.years = years; + + return this; + } + + function daysToMonths (days) { + // 400 years have 146097 days (taking into account leap year rules) + // 400 years have 12 months === 4800 + return days * 4800 / 146097; + } + + function monthsToDays (months) { + // the reverse of daysToMonths + return months * 146097 / 4800; + } + + function as (units) { + var days; + var months; + var milliseconds = this._milliseconds; + + units = normalizeUnits(units); + + if (units === 'month' || units === 'year') { + days = this._days + milliseconds / 864e5; + months = this._months + daysToMonths(days); + return units === 'month' ? months : months / 12; + } else { + // handle milliseconds separately because of floating point math errors (issue #1867) + days = this._days + Math.round(monthsToDays(this._months)); + switch (units) { + case 'week' : return days / 7 + milliseconds / 6048e5; + case 'day' : return days + milliseconds / 864e5; + case 'hour' : return days * 24 + milliseconds / 36e5; + case 'minute' : return days * 1440 + milliseconds / 6e4; + case 'second' : return days * 86400 + milliseconds / 1000; + // Math.floor prevents floating point math errors here + case 'millisecond': return Math.floor(days * 864e5) + milliseconds; + default: throw new Error('Unknown unit ' + units); + } + } + } + + // TODO: Use this.as('ms')? + function duration_as__valueOf () { + return ( + this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6 + ); + } + + function makeAs (alias) { + return function () { + return this.as(alias); + }; + } + + var asMilliseconds = makeAs('ms'); + var asSeconds = makeAs('s'); + var asMinutes = makeAs('m'); + var asHours = makeAs('h'); + var asDays = makeAs('d'); + var asWeeks = makeAs('w'); + var asMonths = makeAs('M'); + var asYears = makeAs('y'); + + function duration_get__get (units) { + units = normalizeUnits(units); + return this[units + 's'](); + } + + function makeGetter(name) { + return function () { + return this._data[name]; + }; + } + + var milliseconds = makeGetter('milliseconds'); + var seconds = makeGetter('seconds'); + var minutes = makeGetter('minutes'); + var hours = makeGetter('hours'); + var days = makeGetter('days'); + var months = makeGetter('months'); + var years = makeGetter('years'); + + function weeks () { + return absFloor(this.days() / 7); + } + + var round = Math.round; + var thresholds = { + s: 45, // seconds to minute + m: 45, // minutes to hour + h: 22, // hours to day + d: 26, // days to month + M: 11 // months to year + }; + + // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize + function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { + return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); + } + + function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) { + var duration = create__createDuration(posNegDuration).abs(); + var seconds = round(duration.as('s')); + var minutes = round(duration.as('m')); + var hours = round(duration.as('h')); + var days = round(duration.as('d')); + var months = round(duration.as('M')); + var years = round(duration.as('y')); + + var a = seconds < thresholds.s && ['s', seconds] || + minutes <= 1 && ['m'] || + minutes < thresholds.m && ['mm', minutes] || + hours <= 1 && ['h'] || + hours < thresholds.h && ['hh', hours] || + days <= 1 && ['d'] || + days < thresholds.d && ['dd', days] || + months <= 1 && ['M'] || + months < thresholds.M && ['MM', months] || + years <= 1 && ['y'] || ['yy', years]; + + a[2] = withoutSuffix; + a[3] = +posNegDuration > 0; + a[4] = locale; + return substituteTimeAgo.apply(null, a); + } + + // This function allows you to set the rounding function for relative time strings + function duration_humanize__getSetRelativeTimeRounding (roundingFunction) { + if (roundingFunction === undefined) { + return round; + } + if (typeof(roundingFunction) === 'function') { + round = roundingFunction; + return true; + } + return false; + } + + // This function allows you to set a threshold for relative time strings + function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) { + if (thresholds[threshold] === undefined) { + return false; + } + if (limit === undefined) { + return thresholds[threshold]; + } + thresholds[threshold] = limit; + return true; + } + + function humanize (withSuffix) { + var locale = this.localeData(); + var output = duration_humanize__relativeTime(this, !withSuffix, locale); + + if (withSuffix) { + output = locale.pastFuture(+this, output); + } + + return locale.postformat(output); + } + + var iso_string__abs = Math.abs; + + function iso_string__toISOString() { + // for ISO strings we do not use the normal bubbling rules: + // * milliseconds bubble up until they become hours + // * days do not bubble at all + // * months bubble up until they become years + // This is because there is no context-free conversion between hours and days + // (think of clock changes) + // and also not between days and months (28-31 days per month) + var seconds = iso_string__abs(this._milliseconds) / 1000; + var days = iso_string__abs(this._days); + var months = iso_string__abs(this._months); + var minutes, hours, years; + + // 3600 seconds -> 60 minutes -> 1 hour + minutes = absFloor(seconds / 60); + hours = absFloor(minutes / 60); + seconds %= 60; + minutes %= 60; + + // 12 months -> 1 year + years = absFloor(months / 12); + months %= 12; + + + // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js + var Y = years; + var M = months; + var D = days; + var h = hours; + var m = minutes; + var s = seconds; + var total = this.asSeconds(); + + if (!total) { + // this is the same as C#'s (Noda) and python (isodate)... + // but not other JS (goog.date) + return 'P0D'; + } + + return (total < 0 ? '-' : '') + + 'P' + + (Y ? Y + 'Y' : '') + + (M ? M + 'M' : '') + + (D ? D + 'D' : '') + + ((h || m || s) ? 'T' : '') + + (h ? h + 'H' : '') + + (m ? m + 'M' : '') + + (s ? s + 'S' : ''); + } + + var duration_prototype__proto = Duration.prototype; + + duration_prototype__proto.abs = duration_abs__abs; + duration_prototype__proto.add = duration_add_subtract__add; + duration_prototype__proto.subtract = duration_add_subtract__subtract; + duration_prototype__proto.as = as; + duration_prototype__proto.asMilliseconds = asMilliseconds; + duration_prototype__proto.asSeconds = asSeconds; + duration_prototype__proto.asMinutes = asMinutes; + duration_prototype__proto.asHours = asHours; + duration_prototype__proto.asDays = asDays; + duration_prototype__proto.asWeeks = asWeeks; + duration_prototype__proto.asMonths = asMonths; + duration_prototype__proto.asYears = asYears; + duration_prototype__proto.valueOf = duration_as__valueOf; + duration_prototype__proto._bubble = bubble; + duration_prototype__proto.get = duration_get__get; + duration_prototype__proto.milliseconds = milliseconds; + duration_prototype__proto.seconds = seconds; + duration_prototype__proto.minutes = minutes; + duration_prototype__proto.hours = hours; + duration_prototype__proto.days = days; + duration_prototype__proto.weeks = weeks; + duration_prototype__proto.months = months; + duration_prototype__proto.years = years; + duration_prototype__proto.humanize = humanize; + duration_prototype__proto.toISOString = iso_string__toISOString; + duration_prototype__proto.toString = iso_string__toISOString; + duration_prototype__proto.toJSON = iso_string__toISOString; + duration_prototype__proto.locale = locale; + duration_prototype__proto.localeData = localeData; + + // Deprecations + duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString); + duration_prototype__proto.lang = lang; + + // Side effect imports + + // FORMATTING + + addFormatToken('X', 0, 0, 'unix'); + addFormatToken('x', 0, 0, 'valueOf'); + + // PARSING + + addRegexToken('x', matchSigned); + addRegexToken('X', matchTimestamp); + addParseToken('X', function (input, array, config) { + config._d = new Date(parseFloat(input, 10) * 1000); + }); + addParseToken('x', function (input, array, config) { + config._d = new Date(toInt(input)); + }); + + // Side effect imports + + + utils_hooks__hooks.version = '2.14.1'; + + setHookCallback(local__createLocal); + + utils_hooks__hooks.fn = momentPrototype; + utils_hooks__hooks.min = min; + utils_hooks__hooks.max = max; + utils_hooks__hooks.now = now; + utils_hooks__hooks.utc = create_utc__createUTC; + utils_hooks__hooks.unix = moment__createUnix; + utils_hooks__hooks.months = lists__listMonths; + utils_hooks__hooks.isDate = isDate; + utils_hooks__hooks.locale = locale_locales__getSetGlobalLocale; + utils_hooks__hooks.invalid = valid__createInvalid; + utils_hooks__hooks.duration = create__createDuration; + utils_hooks__hooks.isMoment = isMoment; + utils_hooks__hooks.weekdays = lists__listWeekdays; + utils_hooks__hooks.parseZone = moment__createInZone; + utils_hooks__hooks.localeData = locale_locales__getLocale; + utils_hooks__hooks.isDuration = isDuration; + utils_hooks__hooks.monthsShort = lists__listMonthsShort; + utils_hooks__hooks.weekdaysMin = lists__listWeekdaysMin; + utils_hooks__hooks.defineLocale = defineLocale; + utils_hooks__hooks.updateLocale = updateLocale; + utils_hooks__hooks.locales = locale_locales__listLocales; + utils_hooks__hooks.weekdaysShort = lists__listWeekdaysShort; + utils_hooks__hooks.normalizeUnits = normalizeUnits; + utils_hooks__hooks.relativeTimeRounding = duration_humanize__getSetRelativeTimeRounding; + utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold; + utils_hooks__hooks.calendarFormat = getCalendarFormat; + utils_hooks__hooks.prototype = momentPrototype; + + var _moment = utils_hooks__hooks; + + return _moment; + +}));
@@ -0,0 +1,11 @@
+var profile = { + resourceTags: { + ignore: function(filename, mid){ + // only include moment/moment + return mid != "moment/moment"; + }, + amd: function(filename, mid){ + return /\.js$/.test(filename); + } + } +};
@@ -0,0 +1,148 @@
+{ + "name": "moment", + "version": "2.14.1", + "description": "Parse, validate, manipulate, and display dates", + "homepage": "http://momentjs.com", + "author": { + "name": "Iskren Ivov Chernev", + "email": "iskren.chernev@gmail.com", + "url": "https://github.com/ichernev" + }, + "contributors": [ + { + "name": "Tim Wood", + "email": "washwithcare@gmail.com", + "url": "http://timwoodcreates.com/" + }, + { + "name": "Rocky Meza", + "url": "http://rockymeza.com" + }, + { + "name": "Matt Johnson", + "email": "mj1856@hotmail.com", + "url": "http://codeofmatt.com" + }, + { + "name": "Isaac Cambron", + "email": "isaac@isaaccambron.com", + "url": "http://isaaccambron.com" + }, + { + "name": "Andre Polykanine", + "email": "andre@oire.org", + "url": "https://github.com/oire" + } + ], + "keywords": [ + "moment", + "date", + "time", + "parse", + "format", + "validate", + "i18n", + "l10n", + "ender" + ], + "main": "./moment.js", + "jsnext:main": "./src/moment.js", + "typings": "./moment.d.ts", + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/moment/moment.git" + }, + "bugs": { + "url": "https://github.com/moment/moment/issues" + }, + "license": "MIT", + "devDependencies": { + "uglify-js": "latest", + "es6-promise": "latest", + "grunt": "~0.4", + "grunt-cli": "latest", + "benchmark": "latest", + "esperanto": "latest", + "grunt-contrib-clean": "latest", + "grunt-contrib-concat": "latest", + "grunt-contrib-copy": "latest", + "grunt-contrib-jshint": "latest", + "grunt-contrib-uglify": "latest", + "grunt-contrib-watch": "latest", + "grunt-env": "latest", + "grunt-jscs": "latest", + "grunt-karma": "latest", + "grunt-nuget": "latest", + "grunt-benchmark": "latest", + "grunt-string-replace": "latest", + "grunt-exec": "latest", + "load-grunt-tasks": "latest", + "karma": "latest", + "karma-chrome-launcher": "latest", + "karma-firefox-launcher": "latest", + "karma-qunit": "latest", + "karma-sauce-launcher": "latest", + "qunit": "^0.7.5", + "qunit-cli": "^0.1.4", + "spacejam": "latest", + "coveralls": "^2.11.2", + "nyc": "^2.1.4" + }, + "ender": "./ender.js", + "dojoBuild": "package.js", + "jspm": { + "files": [ + "moment.js", + "locale" + ], + "map": { + "moment": "./moment" + }, + "buildConfig": { + "uglify": true + } + }, + "scripts": { + "test": "grunt test", + "coverage": "nyc npm test && nyc report", + "coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls" + }, + "spm": { + "main": "moment.js", + "output": [ + "locale/*.js" + ] + }, + "_id": "moment@2.14.1", + "_shasum": "b35b27c47e57ed2ddc70053d6b07becdb291741c", + "_from": "moment@>=2.0.0 <3.0.0", + "_npmVersion": "3.8.6", + "_nodeVersion": "6.1.0", + "_npmUser": { + "name": "ichernev", + "email": "iskren.chernev@gmail.com" + }, + "dist": { + "shasum": "b35b27c47e57ed2ddc70053d6b07becdb291741c", + "tarball": "https://registry.npmjs.org/moment/-/moment-2.14.1.tgz" + }, + "maintainers": [ + { + "name": "timrwood", + "email": "washwithcare@gmail.com" + }, + { + "name": "ichernev", + "email": "iskren.chernev@gmail.com" + } + ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/moment-2.14.1.tgz_1467614674915_0.32715084473602474" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/moment/-/moment-2.14.1.tgz" +}
@@ -0,0 +1,34 @@
+import { daysInMonth } from '../units/month'; +import { YEAR, MONTH, DATE, HOUR, MINUTE, SECOND, MILLISECOND, WEEK, WEEKDAY } from '../units/constants'; +import getParsingFlags from '../create/parsing-flags'; + +export default function checkOverflow (m) { + var overflow; + var a = m._a; + + if (a && getParsingFlags(m).overflow === -2) { + overflow = + a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : + a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : + a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR : + a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : + a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : + a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : + -1; + + if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } + if (getParsingFlags(m)._overflowWeeks && overflow === -1) { + overflow = WEEK; + } + if (getParsingFlags(m)._overflowWeekday && overflow === -1) { + overflow = WEEKDAY; + } + + getParsingFlags(m).overflow = overflow; + } + + return m; +} +
@@ -0,0 +1,21 @@
+export function createDate (y, m, d, h, M, s, ms) { + //can't just apply() to create a date: + //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply + var date = new Date(y, m, d, h, M, s, ms); + + //the date constructor remaps years 0-99 to 1900-1999 + if (y < 100 && y >= 0 && isFinite(date.getFullYear())) { + date.setFullYear(y); + } + return date; +} + +export function createUTCDate (y) { + var date = new Date(Date.UTC.apply(null, arguments)); + + //the Date.UTC function remaps years 0-99 to 1900-1999 + if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) { + date.setUTCFullYear(y); + } + return date; +}
@@ -0,0 +1,108 @@
+import isArray from '../utils/is-array'; +import isObject from '../utils/is-object'; +import isObjectEmpty from '../utils/is-object-empty'; +import isDate from '../utils/is-date'; +import map from '../utils/map'; +import { createInvalid } from './valid'; +import { Moment, isMoment } from '../moment/constructor'; +import { getLocale } from '../locale/locales'; +import { hooks } from '../utils/hooks'; +import checkOverflow from './check-overflow'; +import { isValid } from './valid'; + +import { configFromStringAndArray } from './from-string-and-array'; +import { configFromStringAndFormat } from './from-string-and-format'; +import { configFromString } from './from-string'; +import { configFromArray } from './from-array'; +import { configFromObject } from './from-object'; + +function createFromConfig (config) { + var res = new Moment(checkOverflow(prepareConfig(config))); + if (res._nextDay) { + // Adding is smart enough around DST + res.add(1, 'd'); + res._nextDay = undefined; + } + + return res; +} + +export function prepareConfig (config) { + var input = config._i, + format = config._f; + + config._locale = config._locale || getLocale(config._l); + + if (input === null || (format === undefined && input === '')) { + return createInvalid({nullInput: true}); + } + + if (typeof input === 'string') { + config._i = input = config._locale.preparse(input); + } + + if (isMoment(input)) { + return new Moment(checkOverflow(input)); + } else if (isArray(format)) { + configFromStringAndArray(config); + } else if (isDate(input)) { + config._d = input; + } else if (format) { + configFromStringAndFormat(config); + } else { + configFromInput(config); + } + + if (!isValid(config)) { + config._d = null; + } + + return config; +} + +function configFromInput(config) { + var input = config._i; + if (input === undefined) { + config._d = new Date(hooks.now()); + } else if (isDate(input)) { + config._d = new Date(input.valueOf()); + } else if (typeof input === 'string') { + configFromString(config); + } else if (isArray(input)) { + config._a = map(input.slice(0), function (obj) { + return parseInt(obj, 10); + }); + configFromArray(config); + } else if (typeof(input) === 'object') { + configFromObject(config); + } else if (typeof(input) === 'number') { + // from milliseconds + config._d = new Date(input); + } else { + hooks.createFromInputFallback(config); + } +} + +export function createLocalOrUTC (input, format, locale, strict, isUTC) { + var c = {}; + + if (typeof(locale) === 'boolean') { + strict = locale; + locale = undefined; + } + + if ((isObject(input) && isObjectEmpty(input)) || + (isArray(input) && input.length === 0)) { + input = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c._isAMomentObject = true; + c._useUTC = c._isUTC = isUTC; + c._l = locale; + c._i = input; + c._f = format; + c._strict = strict; + + return createFromConfig(c); +}
@@ -0,0 +1,136 @@
+import { hooks } from '../utils/hooks'; +import { createDate, createUTCDate } from './date-from-array'; +import { daysInYear } from '../units/year'; +import { weekOfYear, weeksInYear, dayOfYearFromWeeks } from '../units/week-calendar-utils'; +import { YEAR, MONTH, DATE, HOUR, MINUTE, SECOND, MILLISECOND } from '../units/constants'; +import { createLocal } from './local'; +import defaults from '../utils/defaults'; +import getParsingFlags from './parsing-flags'; + +function currentDateArray(config) { + // hooks is actually the exported moment object + var nowValue = new Date(hooks.now()); + if (config._useUTC) { + return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()]; + } + return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()]; +} + +// convert an array to a date. +// the array should mirror the parameters below +// note: all values past the year are optional and will default to the lowest possible value. +// [year, month, day , hour, minute, second, millisecond] +export function configFromArray (config) { + var i, date, input = [], currentDate, yearToUse; + + if (config._d) { + return; + } + + currentDate = currentDateArray(config); + + //compute day of the year from weeks and weekdays + if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { + dayOfYearFromWeekInfo(config); + } + + //if the day of the year is set, figure out what it is + if (config._dayOfYear) { + yearToUse = defaults(config._a[YEAR], currentDate[YEAR]); + + if (config._dayOfYear > daysInYear(yearToUse)) { + getParsingFlags(config)._overflowDayOfYear = true; + } + + date = createUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); + } + + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } + + // Zero out whatever was not defaulted, including time + for (; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } + + // Check for 24:00:00.000 + if (config._a[HOUR] === 24 && + config._a[MINUTE] === 0 && + config._a[SECOND] === 0 && + config._a[MILLISECOND] === 0) { + config._nextDay = true; + config._a[HOUR] = 0; + } + + config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input); + // Apply timezone offset from input. The actual utcOffset can be changed + // with parseZone. + if (config._tzm != null) { + config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); + } + + if (config._nextDay) { + config._a[HOUR] = 24; + } +} + +function dayOfYearFromWeekInfo(config) { + var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow; + + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + dow = 1; + doy = 4; + + // TODO: We need to take the current isoWeekYear, but that depends on + // how we interpret now (local, utc, fixed offset). So create + // a now version of current config (take local/utc/offset flags, and + // create now). + weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year); + week = defaults(w.W, 1); + weekday = defaults(w.E, 1); + if (weekday < 1 || weekday > 7) { + weekdayOverflow = true; + } + } else { + dow = config._locale._week.dow; + doy = config._locale._week.doy; + + weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(createLocal(), dow, doy).year); + week = defaults(w.w, 1); + + if (w.d != null) { + // weekday -- low day numbers are considered next week + weekday = w.d; + if (weekday < 0 || weekday > 6) { + weekdayOverflow = true; + } + } else if (w.e != null) { + // local weekday -- counting starts from begining of week + weekday = w.e + dow; + if (w.e < 0 || w.e > 6) { + weekdayOverflow = true; + } + } else { + // default to begining of week + weekday = dow; + } + } + if (week < 1 || week > weeksInYear(weekYear, dow, doy)) { + getParsingFlags(config)._overflowWeeks = true; + } else if (weekdayOverflow != null) { + getParsingFlags(config)._overflowWeekday = true; + } else { + temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy); + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; + } +}
@@ -0,0 +1,16 @@
+import { normalizeObjectUnits } from '../units/aliases'; +import { configFromArray } from './from-array'; +import map from '../utils/map'; + +export function configFromObject(config) { + if (config._d) { + return; + } + + var i = normalizeObjectUnits(config._i); + config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) { + return obj && parseInt(obj, 10); + }); + + configFromArray(config); +}
@@ -0,0 +1,50 @@
+import { copyConfig } from '../moment/constructor'; +import { configFromStringAndFormat } from './from-string-and-format'; +import getParsingFlags from './parsing-flags'; +import { isValid } from './valid'; +import extend from '../utils/extend'; + +// date from string and array of format strings +export function configFromStringAndArray(config) { + var tempConfig, + bestMoment, + + scoreToBeat, + i, + currentScore; + + if (config._f.length === 0) { + getParsingFlags(config).invalidFormat = true; + config._d = new Date(NaN); + return; + } + + for (i = 0; i < config._f.length; i++) { + currentScore = 0; + tempConfig = copyConfig({}, config); + if (config._useUTC != null) { + tempConfig._useUTC = config._useUTC; + } + tempConfig._f = config._f[i]; + configFromStringAndFormat(tempConfig); + + if (!isValid(tempConfig)) { + continue; + } + + // if there is any input that was not parsed add a penalty for that format + currentScore += getParsingFlags(tempConfig).charsLeftOver; + + //or tokens + currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10; + + getParsingFlags(tempConfig).score = currentScore; + + if (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } + } + + extend(config, bestMoment || tempConfig); +}
@@ -0,0 +1,107 @@
+import { configFromISO } from './from-string'; +import { configFromArray } from './from-array'; +import { getParseRegexForToken } from '../parse/regex'; +import { addTimeToArrayFromToken } from '../parse/token'; +import { expandFormat, formatTokenFunctions, formattingTokens } from '../format/format'; +import checkOverflow from './check-overflow'; +import { HOUR } from '../units/constants'; +import { hooks } from '../utils/hooks'; +import getParsingFlags from './parsing-flags'; + +// constant that refers to the ISO standard +hooks.ISO_8601 = function () {}; + +// date from string and format string +export function configFromStringAndFormat(config) { + // TODO: Move this to another part of the creation flow to prevent circular deps + if (config._f === hooks.ISO_8601) { + configFromISO(config); + return; + } + + config._a = []; + getParsingFlags(config).empty = true; + + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var string = '' + config._i, + i, parsedInput, tokens, token, skipped, + stringLength = string.length, + totalParsedInputLength = 0; + + tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; + + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; + // console.log('token', token, 'parsedInput', parsedInput, + // 'regex', getParseRegexForToken(token, config)); + if (parsedInput) { + skipped = string.substr(0, string.indexOf(parsedInput)); + if (skipped.length > 0) { + getParsingFlags(config).unusedInput.push(skipped); + } + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); + totalParsedInputLength += parsedInput.length; + } + // don't parse if it's not a known token + if (formatTokenFunctions[token]) { + if (parsedInput) { + getParsingFlags(config).empty = false; + } + else { + getParsingFlags(config).unusedTokens.push(token); + } + addTimeToArrayFromToken(token, parsedInput, config); + } + else if (config._strict && !parsedInput) { + getParsingFlags(config).unusedTokens.push(token); + } + } + + // add remaining unparsed input length to the string + getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + getParsingFlags(config).unusedInput.push(string); + } + + // clear _12h flag if hour is <= 12 + if (config._a[HOUR] <= 12 && + getParsingFlags(config).bigHour === true && + config._a[HOUR] > 0) { + getParsingFlags(config).bigHour = undefined; + } + + getParsingFlags(config).parsedDateParts = config._a.slice(0); + getParsingFlags(config).meridiem = config._meridiem; + // handle meridiem + config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem); + + configFromArray(config); + checkOverflow(config); +} + + +function meridiemFixWrap (locale, hour, meridiem) { + var isPm; + + if (meridiem == null) { + // nothing to do + return hour; + } + if (locale.meridiemHour != null) { + return locale.meridiemHour(hour, meridiem); + } else if (locale.isPM != null) { + // Fallback + isPm = locale.isPM(meridiem); + if (isPm && hour < 12) { + hour += 12; + } + if (!isPm && hour === 12) { + hour = 0; + } + return hour; + } else { + // this is not supposed to happen + return hour; + } +}
@@ -0,0 +1,120 @@
+import { configFromStringAndFormat } from './from-string-and-format'; +import { hooks } from '../utils/hooks'; +import { deprecate } from '../utils/deprecate'; +import getParsingFlags from './parsing-flags'; + +// iso 8601 regex +// 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) +var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/; +var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/; + +var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/; + +var isoDates = [ + ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], + ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], + ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], + ['GGGG-[W]WW', /\d{4}-W\d\d/, false], + ['YYYY-DDD', /\d{4}-\d{3}/], + ['YYYY-MM', /\d{4}-\d\d/, false], + ['YYYYYYMMDD', /[+-]\d{10}/], + ['YYYYMMDD', /\d{8}/], + // YYYYMM is NOT allowed by the standard + ['GGGG[W]WWE', /\d{4}W\d{3}/], + ['GGGG[W]WW', /\d{4}W\d{2}/, false], + ['YYYYDDD', /\d{7}/] +]; + +// iso time formats and regexes +var isoTimes = [ + ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], + ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], + ['HH:mm:ss', /\d\d:\d\d:\d\d/], + ['HH:mm', /\d\d:\d\d/], + ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], + ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], + ['HHmmss', /\d\d\d\d\d\d/], + ['HHmm', /\d\d\d\d/], + ['HH', /\d\d/] +]; + +var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; + +// date from iso format +export function configFromISO(config) { + var i, l, + string = config._i, + match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string), + allowTime, dateFormat, timeFormat, tzFormat; + + if (match) { + getParsingFlags(config).iso = true; + + for (i = 0, l = isoDates.length; i < l; i++) { + if (isoDates[i][1].exec(match[1])) { + dateFormat = isoDates[i][0]; + allowTime = isoDates[i][2] !== false; + break; + } + } + if (dateFormat == null) { + config._isValid = false; + return; + } + if (match[3]) { + for (i = 0, l = isoTimes.length; i < l; i++) { + if (isoTimes[i][1].exec(match[3])) { + // match[2] should be 'T' or space + timeFormat = (match[2] || ' ') + isoTimes[i][0]; + break; + } + } + if (timeFormat == null) { + config._isValid = false; + return; + } + } + if (!allowTime && timeFormat != null) { + config._isValid = false; + return; + } + if (match[4]) { + if (tzRegex.exec(match[4])) { + tzFormat = 'Z'; + } else { + config._isValid = false; + return; + } + } + config._f = dateFormat + (timeFormat || '') + (tzFormat || ''); + configFromStringAndFormat(config); + } else { + config._isValid = false; + } +} + +// date from iso format or fallback +export function configFromString(config) { + var matched = aspNetJsonRegex.exec(config._i); + + if (matched !== null) { + config._d = new Date(+matched[1]); + return; + } + + configFromISO(config); + if (config._isValid === false) { + delete config._isValid; + hooks.createFromInputFallback(config); + } +} + +hooks.createFromInputFallback = deprecate( + 'moment construction falls back to js Date. This is ' + + 'discouraged and will be removed in upcoming major ' + + 'release. Please refer to ' + + 'http://momentjs.com/guides/#/warnings/js-date/ for more info.', + function (config) { + config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); + } +);
@@ -0,0 +1,5 @@
+import { createLocalOrUTC } from './from-anything'; + +export function createLocal (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, false); +}
@@ -0,0 +1,24 @@
+function defaultParsingFlags() { + // We need to deep clone this object. + return { + empty : false, + unusedTokens : [], + unusedInput : [], + overflow : -2, + charsLeftOver : 0, + nullInput : false, + invalidMonth : null, + invalidFormat : false, + userInvalidated : false, + iso : false, + parsedDateParts : [], + meridiem : null + }; +} + +export default function getParsingFlags(m) { + if (m._pf == null) { + m._pf = defaultParsingFlags(); + } + return m._pf; +}
@@ -0,0 +1,5 @@
+import { createLocalOrUTC } from './from-anything'; + +export function createUTC (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, true).utc(); +}
@@ -0,0 +1,42 @@
+import extend from '../utils/extend'; +import { createUTC } from './utc'; +import getParsingFlags from '../create/parsing-flags'; +import some from '../utils/some'; + +export function isValid(m) { + if (m._isValid == null) { + var flags = getParsingFlags(m); + var parsedParts = some.call(flags.parsedDateParts, function (i) { + return i != null; + }); + m._isValid = !isNaN(m._d.getTime()) && + flags.overflow < 0 && + !flags.empty && + !flags.invalidMonth && + !flags.invalidWeekday && + !flags.nullInput && + !flags.invalidFormat && + !flags.userInvalidated && + (!flags.meridiem || (flags.meridiem && parsedParts)); + + if (m._strict) { + m._isValid = m._isValid && + flags.charsLeftOver === 0 && + flags.unusedTokens.length === 0 && + flags.bigHour === undefined; + } + } + return m._isValid; +} + +export function createInvalid (flags) { + var m = createUTC(NaN); + if (flags != null) { + extend(getParsingFlags(m), flags); + } + else { + getParsingFlags(m).userInvalidated = true; + } + + return m; +}
@@ -0,0 +1,18 @@
+var mathAbs = Math.abs; + +export function abs () { + var data = this._data; + + this._milliseconds = mathAbs(this._milliseconds); + this._days = mathAbs(this._days); + this._months = mathAbs(this._months); + + data.milliseconds = mathAbs(data.milliseconds); + data.seconds = mathAbs(data.seconds); + data.minutes = mathAbs(data.minutes); + data.hours = mathAbs(data.hours); + data.months = mathAbs(data.months); + data.years = mathAbs(data.years); + + return this; +}
@@ -0,0 +1,21 @@
+import { createDuration } from './create'; + +function addSubtract (duration, input, value, direction) { + var other = createDuration(input, value); + + duration._milliseconds += direction * other._milliseconds; + duration._days += direction * other._days; + duration._months += direction * other._months; + + return duration._bubble(); +} + +// supports only 2.0-style add(1, 's') or add(duration) +export function add (input, value) { + return addSubtract(this, input, value, 1); +} + +// supports only 2.0-style subtract(1, 's') or subtract(duration) +export function subtract (input, value) { + return addSubtract(this, input, value, -1); +}
@@ -0,0 +1,55 @@
+import { daysToMonths, monthsToDays } from './bubble'; +import { normalizeUnits } from '../units/aliases'; +import toInt from '../utils/to-int'; + +export function as (units) { + var days; + var months; + var milliseconds = this._milliseconds; + + units = normalizeUnits(units); + + if (units === 'month' || units === 'year') { + days = this._days + milliseconds / 864e5; + months = this._months + daysToMonths(days); + return units === 'month' ? months : months / 12; + } else { + // handle milliseconds separately because of floating point math errors (issue #1867) + days = this._days + Math.round(monthsToDays(this._months)); + switch (units) { + case 'week' : return days / 7 + milliseconds / 6048e5; + case 'day' : return days + milliseconds / 864e5; + case 'hour' : return days * 24 + milliseconds / 36e5; + case 'minute' : return days * 1440 + milliseconds / 6e4; + case 'second' : return days * 86400 + milliseconds / 1000; + // Math.floor prevents floating point math errors here + case 'millisecond': return Math.floor(days * 864e5) + milliseconds; + default: throw new Error('Unknown unit ' + units); + } + } +} + +// TODO: Use this.as('ms')? +export function valueOf () { + return ( + this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6 + ); +} + +function makeAs (alias) { + return function () { + return this.as(alias); + }; +} + +export var asMilliseconds = makeAs('ms'); +export var asSeconds = makeAs('s'); +export var asMinutes = makeAs('m'); +export var asHours = makeAs('h'); +export var asDays = makeAs('d'); +export var asWeeks = makeAs('w'); +export var asMonths = makeAs('M'); +export var asYears = makeAs('y');
@@ -0,0 +1,61 @@
+import absFloor from '../utils/abs-floor'; +import absCeil from '../utils/abs-ceil'; +import { createUTCDate } from '../create/date-from-array'; + +export function bubble () { + var milliseconds = this._milliseconds; + var days = this._days; + var months = this._months; + var data = this._data; + var seconds, minutes, hours, years, monthsFromDays; + + // if we have a mix of positive and negative values, bubble down first + // check: https://github.com/moment/moment/issues/2166 + if (!((milliseconds >= 0 && days >= 0 && months >= 0) || + (milliseconds <= 0 && days <= 0 && months <= 0))) { + milliseconds += absCeil(monthsToDays(months) + days) * 864e5; + days = 0; + months = 0; + } + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absFloor(milliseconds / 1000); + data.seconds = seconds % 60; + + minutes = absFloor(seconds / 60); + data.minutes = minutes % 60; + + hours = absFloor(minutes / 60); + data.hours = hours % 24; + + days += absFloor(hours / 24); + + // convert days to months + monthsFromDays = absFloor(daysToMonths(days)); + months += monthsFromDays; + days -= absCeil(monthsToDays(monthsFromDays)); + + // 12 months -> 1 year + years = absFloor(months / 12); + months %= 12; + + data.days = days; + data.months = months; + data.years = years; + + return this; +} + +export function daysToMonths (days) { + // 400 years have 146097 days (taking into account leap year rules) + // 400 years have 12 months === 4800 + return days * 4800 / 146097; +} + +export function monthsToDays (months) { + // the reverse of daysToMonths + return months * 146097 / 4800; +}
@@ -0,0 +1,41 @@
+import { normalizeObjectUnits } from '../units/aliases'; +import { getLocale } from '../locale/locales'; + +export function Duration (duration) { + var normalizedInput = normalizeObjectUnits(duration), + years = normalizedInput.year || 0, + quarters = normalizedInput.quarter || 0, + months = normalizedInput.month || 0, + weeks = normalizedInput.week || 0, + days = normalizedInput.day || 0, + hours = normalizedInput.hour || 0, + minutes = normalizedInput.minute || 0, + seconds = normalizedInput.second || 0, + milliseconds = normalizedInput.millisecond || 0; + + // representation for dateAddRemove + this._milliseconds = +milliseconds + + seconds * 1e3 + // 1000 + minutes * 6e4 + // 1000 * 60 + hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978 + // Because of dateAddRemove treats 24 hours as different from a + // day when working around DST, we need to store them separately + this._days = +days + + weeks * 7; + // It is impossible translate months into days without knowing + // which months you are are talking about, so we have to store + // it separately. + this._months = +months + + quarters * 3 + + years * 12; + + this._data = {}; + + this._locale = getLocale(); + + this._bubble(); +} + +export function isDuration (obj) { + return obj instanceof Duration; +}
@@ -0,0 +1,118 @@
+import { Duration, isDuration } from './constructor'; +import toInt from '../utils/to-int'; +import hasOwnProp from '../utils/has-own-prop'; +import { DATE, HOUR, MINUTE, SECOND, MILLISECOND } from '../units/constants'; +import { cloneWithOffset } from '../units/offset'; +import { createLocal } from '../create/local'; + +// ASP.NET json date format regex +var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/; + +// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html +// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere +// and further modified to allow for strings containing both week and day +var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/; + +export function createDuration (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + diffRes; + + if (isDuration(input)) { + duration = { + ms : input._milliseconds, + d : input._days, + M : input._months + }; + } else if (typeof input === 'number') { + duration = {}; + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (!!(match = aspNetRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : 0, + d : toInt(match[DATE]) * sign, + h : toInt(match[HOUR]) * sign, + m : toInt(match[MINUTE]) * sign, + s : toInt(match[SECOND]) * sign, + ms : toInt(match[MILLISECOND]) * sign + }; + } else if (!!(match = isoRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : parseIso(match[2], sign), + M : parseIso(match[3], sign), + w : parseIso(match[4], sign), + d : parseIso(match[5], sign), + h : parseIso(match[6], sign), + m : parseIso(match[7], sign), + s : parseIso(match[8], sign) + }; + } else if (duration == null) {// checks for null or undefined + duration = {}; + } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) { + diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to)); + + duration = {}; + duration.ms = diffRes.milliseconds; + duration.M = diffRes.months; + } + + ret = new Duration(duration); + + if (isDuration(input) && hasOwnProp(input, '_locale')) { + ret._locale = input._locale; + } + + return ret; +} + +createDuration.fn = Duration.prototype; + +function parseIso (inp, sign) { + // We'd normally use ~~inp for this, but unfortunately it also + // converts floats to ints. + // inp may be undefined, so careful calling replace on it. + var res = inp && parseFloat(inp.replace(',', '.')); + // apply sign while we're at it + return (isNaN(res) ? 0 : res) * sign; +} + +function positiveMomentsDifference(base, other) { + var res = {milliseconds: 0, months: 0}; + + res.months = other.month() - base.month() + + (other.year() - base.year()) * 12; + if (base.clone().add(res.months, 'M').isAfter(other)) { + --res.months; + } + + res.milliseconds = +other - +(base.clone().add(res.months, 'M')); + + return res; +} + +function momentsDifference(base, other) { + var res; + if (!(base.isValid() && other.isValid())) { + return {milliseconds: 0, months: 0}; + } + + other = cloneWithOffset(other, base); + if (base.isBefore(other)) { + res = positiveMomentsDifference(base, other); + } else { + res = positiveMomentsDifference(other, base); + res.milliseconds = -res.milliseconds; + res.months = -res.months; + } + + return res; +}
@@ -0,0 +1,16 @@
+// Side effect imports +import './prototype'; + +import { createDuration } from './create'; +import { isDuration } from './constructor'; +import { + getSetRelativeTimeRounding, + getSetRelativeTimeThreshold +} from './humanize'; + +export { + createDuration, + isDuration, + getSetRelativeTimeRounding, + getSetRelativeTimeThreshold +};
@@ -0,0 +1,25 @@
+import { normalizeUnits } from '../units/aliases'; +import absFloor from '../utils/abs-floor'; + +export function get (units) { + units = normalizeUnits(units); + return this[units + 's'](); +} + +function makeGetter(name) { + return function () { + return this._data[name]; + }; +} + +export var milliseconds = makeGetter('milliseconds'); +export var seconds = makeGetter('seconds'); +export var minutes = makeGetter('minutes'); +export var hours = makeGetter('hours'); +export var days = makeGetter('days'); +export var months = makeGetter('months'); +export var years = makeGetter('years'); + +export function weeks () { + return absFloor(this.days() / 7); +}
@@ -0,0 +1,76 @@
+import { createDuration } from './create'; + +var round = Math.round; +var thresholds = { + s: 45, // seconds to minute + m: 45, // minutes to hour + h: 22, // hours to day + d: 26, // days to month + M: 11 // months to year +}; + +// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize +function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { + return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); +} + +function relativeTime (posNegDuration, withoutSuffix, locale) { + var duration = createDuration(posNegDuration).abs(); + var seconds = round(duration.as('s')); + var minutes = round(duration.as('m')); + var hours = round(duration.as('h')); + var days = round(duration.as('d')); + var months = round(duration.as('M')); + var years = round(duration.as('y')); + + var a = seconds < thresholds.s && ['s', seconds] || + minutes <= 1 && ['m'] || + minutes < thresholds.m && ['mm', minutes] || + hours <= 1 && ['h'] || + hours < thresholds.h && ['hh', hours] || + days <= 1 && ['d'] || + days < thresholds.d && ['dd', days] || + months <= 1 && ['M'] || + months < thresholds.M && ['MM', months] || + years <= 1 && ['y'] || ['yy', years]; + + a[2] = withoutSuffix; + a[3] = +posNegDuration > 0; + a[4] = locale; + return substituteTimeAgo.apply(null, a); +} + +// This function allows you to set the rounding function for relative time strings +export function getSetRelativeTimeRounding (roundingFunction) { + if (roundingFunction === undefined) { + return round; + } + if (typeof(roundingFunction) === 'function') { + round = roundingFunction; + return true; + } + return false; +} + +// This function allows you to set a threshold for relative time strings +export function getSetRelativeTimeThreshold (threshold, limit) { + if (thresholds[threshold] === undefined) { + return false; + } + if (limit === undefined) { + return thresholds[threshold]; + } + thresholds[threshold] = limit; + return true; +} + +export function humanize (withSuffix) { + var locale = this.localeData(); + var output = relativeTime(this, !withSuffix, locale); + + if (withSuffix) { + output = locale.pastFuture(+this, output); + } + + return locale.postformat(output); +}
@@ -0,0 +1,52 @@
+import absFloor from '../utils/abs-floor'; +var abs = Math.abs; + +export function toISOString() { + // for ISO strings we do not use the normal bubbling rules: + // * milliseconds bubble up until they become hours + // * days do not bubble at all + // * months bubble up until they become years + // This is because there is no context-free conversion between hours and days + // (think of clock changes) + // and also not between days and months (28-31 days per month) + var seconds = abs(this._milliseconds) / 1000; + var days = abs(this._days); + var months = abs(this._months); + var minutes, hours, years; + + // 3600 seconds -> 60 minutes -> 1 hour + minutes = absFloor(seconds / 60); + hours = absFloor(minutes / 60); + seconds %= 60; + minutes %= 60; + + // 12 months -> 1 year + years = absFloor(months / 12); + months %= 12; + + + // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js + var Y = years; + var M = months; + var D = days; + var h = hours; + var m = minutes; + var s = seconds; + var total = this.asSeconds(); + + if (!total) { + // this is the same as C#'s (Noda) and python (isodate)... + // but not other JS (goog.date) + return 'P0D'; + } + + return (total < 0 ? '-' : '') + + 'P' + + (Y ? Y + 'Y' : '') + + (M ? M + 'M' : '') + + (D ? D + 'D' : '') + + ((h || m || s) ? 'T' : '') + + (h ? h + 'H' : '') + + (m ? m + 'M' : '') + + (s ? s + 'S' : ''); +}
@@ -0,0 +1,48 @@
+import { Duration } from './constructor'; + +var proto = Duration.prototype; + +import { abs } from './abs'; +import { add, subtract } from './add-subtract'; +import { as, asMilliseconds, asSeconds, asMinutes, asHours, asDays, asWeeks, asMonths, asYears, valueOf } from './as'; +import { bubble } from './bubble'; +import { get, milliseconds, seconds, minutes, hours, days, months, years, weeks } from './get'; +import { humanize } from './humanize'; +import { toISOString } from './iso-string'; +import { lang, locale, localeData } from '../moment/locale'; + +proto.abs = abs; +proto.add = add; +proto.subtract = subtract; +proto.as = as; +proto.asMilliseconds = asMilliseconds; +proto.asSeconds = asSeconds; +proto.asMinutes = asMinutes; +proto.asHours = asHours; +proto.asDays = asDays; +proto.asWeeks = asWeeks; +proto.asMonths = asMonths; +proto.asYears = asYears; +proto.valueOf = valueOf; +proto._bubble = bubble; +proto.get = get; +proto.milliseconds = milliseconds; +proto.seconds = seconds; +proto.minutes = minutes; +proto.hours = hours; +proto.days = days; +proto.weeks = weeks; +proto.months = months; +proto.years = years; +proto.humanize = humanize; +proto.toISOString = toISOString; +proto.toString = toISOString; +proto.toJSON = toISOString; +proto.locale = locale; +proto.localeData = localeData; + +// Deprecations +import { deprecate } from '../utils/deprecate'; + +proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString); +proto.lang = lang;
@@ -0,0 +1,91 @@
+import zeroFill from '../utils/zero-fill'; + +export var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g; + +var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g; + +var formatFunctions = {}; + +export var formatTokenFunctions = {}; + +// token: 'M' +// padded: ['MM', 2] +// ordinal: 'Mo' +// callback: function () { this.month() + 1 } +export function addFormatToken (token, padded, ordinal, callback) { + var func = callback; + if (typeof callback === 'string') { + func = function () { + return this[callback](); + }; + } + if (token) { + formatTokenFunctions[token] = func; + } + if (padded) { + formatTokenFunctions[padded[0]] = function () { + return zeroFill(func.apply(this, arguments), padded[1], padded[2]); + }; + } + if (ordinal) { + formatTokenFunctions[ordinal] = function () { + return this.localeData().ordinal(func.apply(this, arguments), token); + }; + } +} + +function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + return input.replace(/^\[|\]$/g, ''); + } + return input.replace(/\\/g, ''); +} + +function makeFormatFunction(format) { + var array = format.match(formattingTokens), i, length; + + for (i = 0, length = array.length; i < length; i++) { + if (formatTokenFunctions[array[i]]) { + array[i] = formatTokenFunctions[array[i]]; + } else { + array[i] = removeFormattingTokens(array[i]); + } + } + + return function (mom) { + var output = '', i; + for (i = 0; i < length; i++) { + output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; + } + return output; + }; +} + +// format date using native date object +export function formatMoment(m, format) { + if (!m.isValid()) { + return m.localeData().invalidDate(); + } + + format = expandFormat(format, m.localeData()); + formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format); + + return formatFunctions[format](m); +} + +export function expandFormat(format, locale) { + var i = 5; + + function replaceLongDateFormatTokens(input) { + return locale.longDateFormat(input) || input; + } + + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } + + return format; +}
@@ -0,0 +1,44 @@
+import { defaultCalendar } from './calendar'; +import { defaultLongDateFormat } from './formats'; +import { defaultInvalidDate } from './invalid'; +import { defaultOrdinal, defaultOrdinalParse } from './ordinal'; +import { defaultRelativeTime } from './relative'; + +// months +import { + defaultLocaleMonths, + defaultLocaleMonthsShort, +} from '../units/month'; + +// week +import { defaultLocaleWeek } from '../units/week'; + +// weekdays +import { + defaultLocaleWeekdays, + defaultLocaleWeekdaysMin, + defaultLocaleWeekdaysShort, +} from '../units/day-of-week'; + +// meridiem +import { defaultLocaleMeridiemParse } from '../units/hour'; + +export var baseConfig = { + calendar: defaultCalendar, + longDateFormat: defaultLongDateFormat, + invalidDate: defaultInvalidDate, + ordinal: defaultOrdinal, + ordinalParse: defaultOrdinalParse, + relativeTime: defaultRelativeTime, + + months: defaultLocaleMonths, + monthsShort: defaultLocaleMonthsShort, + + week: defaultLocaleWeek, + + weekdays: defaultLocaleWeekdays, + weekdaysMin: defaultLocaleWeekdaysMin, + weekdaysShort: defaultLocaleWeekdaysShort, + + meridiemParse: defaultLocaleMeridiemParse +};
@@ -0,0 +1,15 @@
+export var defaultCalendar = { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' +}; + +import isFunction from '../utils/is-function'; + +export function calendar (key, mom, now) { + var output = this._calendar[key] || this._calendar['sameElse']; + return isFunction(output) ? output.call(mom, now) : output; +}
@@ -0,0 +1,5 @@
+export function Locale(config) { + if (config != null) { + this.set(config); + } +}
@@ -0,0 +1,15 @@
+import './prototype'; +import { getSetGlobalLocale } from './locales'; +import toInt from '../utils/to-int'; + +getSetGlobalLocale('en', { + ordinalParse: /\d{1,2}(th|st|nd|rd)/, + ordinal : function (number) { + var b = number % 10, + output = (toInt(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } +});
@@ -0,0 +1,23 @@
+export var defaultLongDateFormat = { + LTS : 'h:mm:ss A', + LT : 'h:mm A', + L : 'MM/DD/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY h:mm A', + LLLL : 'dddd, MMMM D, YYYY h:mm A' +}; + +export function longDateFormat (key) { + var format = this._longDateFormat[key], + formatUpper = this._longDateFormat[key.toUpperCase()]; + + if (format || !formatUpper) { + return format; + } + + this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) { + return val.slice(1); + }); + + return this._longDateFormat[key]; +}
@@ -0,0 +1,5 @@
+export var defaultInvalidDate = 'Invalid date'; + +export function invalidDate () { + return this._invalidDate; +}
@@ -0,0 +1,92 @@
+import { getLocale } from './locales'; +import { createUTC } from '../create/utc'; + +function get (format, index, field, setter) { + var locale = getLocale(); + var utc = createUTC().set(setter, index); + return locale[field](utc, format); +} + +function listMonthsImpl (format, index, field) { + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + + if (index != null) { + return get(format, index, field, 'month'); + } + + var i; + var out = []; + for (i = 0; i < 12; i++) { + out[i] = get(format, i, field, 'month'); + } + return out; +} + +// () +// (5) +// (fmt, 5) +// (fmt) +// (true) +// (true, 5) +// (true, fmt, 5) +// (true, fmt) +function listWeekdaysImpl (localeSorted, format, index, field) { + if (typeof localeSorted === 'boolean') { + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + } else { + format = localeSorted; + index = format; + localeSorted = false; + + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + } + + var locale = getLocale(), + shift = localeSorted ? locale._week.dow : 0; + + if (index != null) { + return get(format, (index + shift) % 7, field, 'day'); + } + + var i; + var out = []; + for (i = 0; i < 7; i++) { + out[i] = get(format, (i + shift) % 7, field, 'day'); + } + return out; +} + +export function listMonths (format, index) { + return listMonthsImpl(format, index, 'months'); +} + +export function listMonthsShort (format, index) { + return listMonthsImpl(format, index, 'monthsShort'); +} + +export function listWeekdays (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdays'); +} + +export function listWeekdaysShort (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort'); +} + +export function listWeekdaysMin (localeSorted, format, index) { + return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin'); +}
@@ -0,0 +1,39 @@
+// Side effect imports +import './prototype'; + +import { + getSetGlobalLocale, + defineLocale, + updateLocale, + getLocale, + listLocales +} from './locales'; + +import { + listMonths, + listMonthsShort, + listWeekdays, + listWeekdaysShort, + listWeekdaysMin +} from './lists'; + +export { + getSetGlobalLocale, + defineLocale, + updateLocale, + getLocale, + listLocales, + listMonths, + listMonthsShort, + listWeekdays, + listWeekdaysShort, + listWeekdaysMin +}; + +import { deprecate } from '../utils/deprecate'; +import { hooks } from '../utils/hooks'; + +hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale); +hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale); + +import './en';
@@ -0,0 +1,171 @@
+import isArray from '../utils/is-array'; +import hasOwnProp from '../utils/has-own-prop'; +import isUndefined from '../utils/is-undefined'; +import compareArrays from '../utils/compare-arrays'; +import { deprecateSimple } from '../utils/deprecate'; +import { mergeConfigs } from './set'; +import { Locale } from './constructor'; +import keys from '../utils/keys'; + +import { baseConfig } from './base-config'; + +// internal storage for locale config files +var locales = {}; +var globalLocale; + +function normalizeLocale(key) { + return key ? key.toLowerCase().replace('_', '-') : key; +} + +// pick the locale from the array +// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each +// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root +function chooseLocale(names) { + var i = 0, j, next, locale, split; + + while (i < names.length) { + split = normalizeLocale(names[i]).split('-'); + j = split.length; + next = normalizeLocale(names[i + 1]); + next = next ? next.split('-') : null; + while (j > 0) { + locale = loadLocale(split.slice(0, j).join('-')); + if (locale) { + return locale; + } + if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { + //the next array item is better than a shallower substring of this one + break; + } + j--; + } + i++; + } + return null; +} + +function loadLocale(name) { + var oldLocale = null; + // TODO: Find a better way to register and load all the locales in Node + if (!locales[name] && (typeof module !== 'undefined') && + module && module.exports) { + try { + oldLocale = globalLocale._abbr; + require('./locale/' + name); + // because defineLocale currently also sets the global locale, we + // want to undo that for lazy loaded locales + getSetGlobalLocale(oldLocale); + } catch (e) { } + } + return locales[name]; +} + +// This function will load locale and then set the global locale. If +// no arguments are passed in, it will simply return the current global +// locale key. +export function getSetGlobalLocale (key, values) { + var data; + if (key) { + if (isUndefined(values)) { + data = getLocale(key); + } + else { + data = defineLocale(key, values); + } + + if (data) { + // moment.duration._locale = moment._locale = data; + globalLocale = data; + } + } + + return globalLocale._abbr; +} + +export function defineLocale (name, config) { + if (config !== null) { + var parentConfig = baseConfig; + config.abbr = name; + if (locales[name] != null) { + deprecateSimple('defineLocaleOverride', + 'use moment.updateLocale(localeName, config) to change ' + + 'an existing locale. moment.defineLocale(localeName, ' + + 'config) should only be used for creating a new locale ' + + 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.'); + parentConfig = locales[name]._config; + } else if (config.parentLocale != null) { + if (locales[config.parentLocale] != null) { + parentConfig = locales[config.parentLocale]._config; + } else { + // treat as if there is no base config + deprecateSimple('parentLocaleUndefined', + 'specified parentLocale is not defined yet. See http://momentjs.com/guides/#/warnings/parent-locale/'); + } + } + locales[name] = new Locale(mergeConfigs(parentConfig, config)); + + // backwards compat for now: also set the locale + getSetGlobalLocale(name); + + return locales[name]; + } else { + // useful for testing + delete locales[name]; + return null; + } +} + +export function updateLocale(name, config) { + if (config != null) { + var locale, parentConfig = baseConfig; + // MERGE + if (locales[name] != null) { + parentConfig = locales[name]._config; + } + config = mergeConfigs(parentConfig, config); + locale = new Locale(config); + locale.parentLocale = locales[name]; + locales[name] = locale; + + // backwards compat for now: also set the locale + getSetGlobalLocale(name); + } else { + // pass null for config to unupdate, useful for tests + if (locales[name] != null) { + if (locales[name].parentLocale != null) { + locales[name] = locales[name].parentLocale; + } else if (locales[name] != null) { + delete locales[name]; + } + } + } + return locales[name]; +} + +// returns locale data +export function getLocale (key) { + var locale; + + if (key && key._locale && key._locale._abbr) { + key = key._locale._abbr; + } + + if (!key) { + return globalLocale; + } + + if (!isArray(key)) { + //short-circuit everything else + locale = loadLocale(key); + if (locale) { + return locale; + } + key = [key]; + } + + return chooseLocale(key); +} + +export function listLocales() { + return keys(locales); +}
@@ -0,0 +1,7 @@
+export var defaultOrdinal = '%d'; +export var defaultOrdinalParse = /\d{1,2}/; + +export function ordinal (number) { + return this._ordinal.replace('%d', number); +} +
@@ -0,0 +1,3 @@
+export function preParsePostFormat (string) { + return string; +}
@@ -0,0 +1,69 @@
+import { Locale } from './constructor'; + +var proto = Locale.prototype; + +import { calendar } from './calendar'; +import { longDateFormat } from './formats'; +import { invalidDate } from './invalid'; +import { ordinal } from './ordinal'; +import { preParsePostFormat } from './pre-post-format'; +import { relativeTime, pastFuture } from './relative'; +import { set } from './set'; + +proto.calendar = calendar; +proto.longDateFormat = longDateFormat; +proto.invalidDate = invalidDate; +proto.ordinal = ordinal; +proto.preparse = preParsePostFormat; +proto.postformat = preParsePostFormat; +proto.relativeTime = relativeTime; +proto.pastFuture = pastFuture; +proto.set = set; + +// Month +import { + localeMonthsParse, + localeMonths, + localeMonthsShort, + monthsRegex, + monthsShortRegex +} from '../units/month'; + +proto.months = localeMonths; +proto.monthsShort = localeMonthsShort; +proto.monthsParse = localeMonthsParse; +proto.monthsRegex = monthsRegex; +proto.monthsShortRegex = monthsShortRegex; + +// Week +import { localeWeek, localeFirstDayOfYear, localeFirstDayOfWeek } from '../units/week'; +proto.week = localeWeek; +proto.firstDayOfYear = localeFirstDayOfYear; +proto.firstDayOfWeek = localeFirstDayOfWeek; + +// Day of Week +import { + localeWeekdaysParse, + localeWeekdays, + localeWeekdaysMin, + localeWeekdaysShort, + + weekdaysRegex, + weekdaysShortRegex, + weekdaysMinRegex +} from '../units/day-of-week'; + +proto.weekdays = localeWeekdays; +proto.weekdaysMin = localeWeekdaysMin; +proto.weekdaysShort = localeWeekdaysShort; +proto.weekdaysParse = localeWeekdaysParse; + +proto.weekdaysRegex = weekdaysRegex; +proto.weekdaysShortRegex = weekdaysShortRegex; +proto.weekdaysMinRegex = weekdaysMinRegex; + +// Hours +import { localeIsPM, localeMeridiem } from '../units/hour'; + +proto.isPM = localeIsPM; +proto.meridiem = localeMeridiem;
@@ -0,0 +1,29 @@
+export var defaultRelativeTime = { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' +}; + +import isFunction from '../utils/is-function'; + +export function relativeTime (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (isFunction(output)) ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); +} + +export function pastFuture (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return isFunction(format) ? format(output) : format.replace(/%s/i, output); +}
@@ -0,0 +1,46 @@
+import isFunction from '../utils/is-function'; +import extend from '../utils/extend'; +import isObject from '../utils/is-object'; +import hasOwnProp from '../utils/has-own-prop'; + +export function set (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (isFunction(prop)) { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + this._config = config; + // Lenient ordinal parsing accepts just a number in addition to + // number + (possibly) stuff coming from _ordinalParseLenient. + this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source); +} + +export function mergeConfigs(parentConfig, childConfig) { + var res = extend({}, parentConfig), prop; + for (prop in childConfig) { + if (hasOwnProp(childConfig, prop)) { + if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) { + res[prop] = {}; + extend(res[prop], parentConfig[prop]); + extend(res[prop], childConfig[prop]); + } else if (childConfig[prop] != null) { + res[prop] = childConfig[prop]; + } else { + delete res[prop]; + } + } + } + for (prop in parentConfig) { + if (hasOwnProp(parentConfig, prop) && + !hasOwnProp(childConfig, prop) && + isObject(parentConfig[prop])) { + // make sure changes to properties don't modify parent config + res[prop] = extend({}, res[prop]); + } + } + return res; +}
@@ -0,0 +1,55 @@
+import { get, set } from './get-set'; +import { setMonth } from '../units/month'; +import { createDuration } from '../duration/create'; +import { deprecateSimple } from '../utils/deprecate'; +import { hooks } from '../utils/hooks'; +import absRound from '../utils/abs-round'; + + +// TODO: remove 'name' arg after deprecation is removed +function createAdder(direction, name) { + return function (val, period) { + var dur, tmp; + //invert the arguments, but complain about it + if (period !== null && !isNaN(+period)) { + deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' + + 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.'); + tmp = val; val = period; period = tmp; + } + + val = typeof val === 'string' ? +val : val; + dur = createDuration(val, period); + addSubtract(this, dur, direction); + return this; + }; +} + +export function addSubtract (mom, duration, isAdding, updateOffset) { + var milliseconds = duration._milliseconds, + days = absRound(duration._days), + months = absRound(duration._months); + + if (!mom.isValid()) { + // No op + return; + } + + updateOffset = updateOffset == null ? true : updateOffset; + + if (milliseconds) { + mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding); + } + if (days) { + set(mom, 'Date', get(mom, 'Date') + days * isAdding); + } + if (months) { + setMonth(mom, get(mom, 'Month') + months * isAdding); + } + if (updateOffset) { + hooks.updateOffset(mom, days || months); + } +} + +export var add = createAdder(1, 'add'); +export var subtract = createAdder(-1, 'subtract'); +
@@ -0,0 +1,26 @@
+import { createLocal } from '../create/local'; +import { cloneWithOffset } from '../units/offset'; +import isFunction from '../utils/is-function'; +import { hooks } from '../utils/hooks'; + +export function getCalendarFormat(myMoment, now) { + var diff = myMoment.diff(now, 'days', true); + return diff < -6 ? 'sameElse' : + diff < -1 ? 'lastWeek' : + diff < 0 ? 'lastDay' : + diff < 1 ? 'sameDay' : + diff < 2 ? 'nextDay' : + diff < 7 ? 'nextWeek' : 'sameElse'; +} + +export function calendar (time, formats) { + // We want to compare the start of today, vs this. + // Getting start-of-today depends on whether we're local/utc/offset or not. + var now = time || createLocal(), + sod = cloneWithOffset(now, this).startOf('day'), + format = hooks.calendarFormat(this, sod) || 'sameElse'; + + var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]); + + return this.format(output || this.localeData().calendar(format, this, createLocal(now))); +}
@@ -0,0 +1,5 @@
+import { Moment } from './constructor'; + +export function clone () { + return new Moment(this); +}
@@ -0,0 +1,59 @@
+import { isMoment } from './constructor'; +import { normalizeUnits } from '../units/aliases'; +import { createLocal } from '../create/local'; +import isUndefined from '../utils/is-undefined'; + +export function isAfter (input, units) { + var localInput = isMoment(input) ? input : createLocal(input); + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(!isUndefined(units) ? units : 'millisecond'); + if (units === 'millisecond') { + return this.valueOf() > localInput.valueOf(); + } else { + return localInput.valueOf() < this.clone().startOf(units).valueOf(); + } +} + +export function isBefore (input, units) { + var localInput = isMoment(input) ? input : createLocal(input); + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(!isUndefined(units) ? units : 'millisecond'); + if (units === 'millisecond') { + return this.valueOf() < localInput.valueOf(); + } else { + return this.clone().endOf(units).valueOf() < localInput.valueOf(); + } +} + +export function isBetween (from, to, units, inclusivity) { + inclusivity = inclusivity || '()'; + return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) && + (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units)); +} + +export function isSame (input, units) { + var localInput = isMoment(input) ? input : createLocal(input), + inputMs; + if (!(this.isValid() && localInput.isValid())) { + return false; + } + units = normalizeUnits(units || 'millisecond'); + if (units === 'millisecond') { + return this.valueOf() === localInput.valueOf(); + } else { + inputMs = localInput.valueOf(); + return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf(); + } +} + +export function isSameOrAfter (input, units) { + return this.isSame(input, units) || this.isAfter(input,units); +} + +export function isSameOrBefore (input, units) { + return this.isSame(input, units) || this.isBefore(input,units); +}
@@ -0,0 +1,74 @@
+import { hooks } from '../utils/hooks'; +import hasOwnProp from '../utils/has-own-prop'; +import isUndefined from '../utils/is-undefined'; +import getParsingFlags from '../create/parsing-flags'; + +// Plugins that add properties should also add the key here (null value), +// so we can properly clone ourselves. +var momentProperties = hooks.momentProperties = []; + +export function copyConfig(to, from) { + var i, prop, val; + + if (!isUndefined(from._isAMomentObject)) { + to._isAMomentObject = from._isAMomentObject; + } + if (!isUndefined(from._i)) { + to._i = from._i; + } + if (!isUndefined(from._f)) { + to._f = from._f; + } + if (!isUndefined(from._l)) { + to._l = from._l; + } + if (!isUndefined(from._strict)) { + to._strict = from._strict; + } + if (!isUndefined(from._tzm)) { + to._tzm = from._tzm; + } + if (!isUndefined(from._isUTC)) { + to._isUTC = from._isUTC; + } + if (!isUndefined(from._offset)) { + to._offset = from._offset; + } + if (!isUndefined(from._pf)) { + to._pf = getParsingFlags(from); + } + if (!isUndefined(from._locale)) { + to._locale = from._locale; + } + + if (momentProperties.length > 0) { + for (i in momentProperties) { + prop = momentProperties[i]; + val = from[prop]; + if (!isUndefined(val)) { + to[prop] = val; + } + } + } + + return to; +} + +var updateInProgress = false; + +// Moment prototype object +export function Moment(config) { + copyConfig(this, config); + this._d = new Date(config._d != null ? config._d.getTime() : NaN); + // Prevent infinite loop in case updateOffset creates new moment + // objects. + if (updateInProgress === false) { + updateInProgress = true; + hooks.updateOffset(this); + updateInProgress = false; + } +} + +export function isMoment (obj) { + return obj instanceof Moment || (obj != null && obj._isAMomentObject != null); +}
@@ -0,0 +1,9 @@
+export function creationData() { + return { + input: this._i, + format: this._f, + locale: this._locale, + isUTC: this._isUTC, + strict: this._strict + }; +}
@@ -0,0 +1,62 @@
+import absFloor from '../utils/abs-floor'; +import { cloneWithOffset } from '../units/offset'; +import { normalizeUnits } from '../units/aliases'; + +export function diff (input, units, asFloat) { + var that, + zoneDelta, + delta, output; + + if (!this.isValid()) { + return NaN; + } + + that = cloneWithOffset(input, this); + + if (!that.isValid()) { + return NaN; + } + + zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4; + + units = normalizeUnits(units); + + if (units === 'year' || units === 'month' || units === 'quarter') { + output = monthDiff(this, that); + if (units === 'quarter') { + output = output / 3; + } else if (units === 'year') { + output = output / 12; + } + } else { + delta = this - that; + output = units === 'second' ? delta / 1e3 : // 1000 + units === 'minute' ? delta / 6e4 : // 1000 * 60 + units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60 + units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst + units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst + delta; + } + return asFloat ? output : absFloor(output); +} + +function monthDiff (a, b) { + // difference in months + var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()), + // b is in (anchor - 1 month, anchor + 1 month) + anchor = a.clone().add(wholeMonthDiff, 'months'), + anchor2, adjust; + + if (b - anchor < 0) { + anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor - anchor2); + } else { + anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor2 - anchor); + } + + //check for negative zero, return zero if negative zero + return -(wholeMonthDiff + adjust) || 0; +}
@@ -0,0 +1,32 @@
+import { formatMoment } from '../format/format'; +import { hooks } from '../utils/hooks'; +import isFunction from '../utils/is-function'; + +hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ'; +hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]'; + +export function toString () { + return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); +} + +export function toISOString () { + var m = this.clone().utc(); + if (0 < m.year() && m.year() <= 9999) { + if (isFunction(Date.prototype.toISOString)) { + // native implementation is ~50x faster, use it when we can + return this.toDate().toISOString(); + } else { + return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + } else { + return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } +} + +export function format (inputString) { + if (!inputString) { + inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat; + } + var output = formatMoment(this, inputString); + return this.localeData().postformat(output); +}
@@ -0,0 +1,17 @@
+import { createDuration } from '../duration/create'; +import { createLocal } from '../create/local'; +import { isMoment } from '../moment/constructor'; + +export function from (time, withoutSuffix) { + if (this.isValid() && + ((isMoment(time) && time.isValid()) || + createLocal(time).isValid())) { + return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); + } else { + return this.localeData().invalidDate(); + } +} + +export function fromNow (withoutSuffix) { + return this.from(createLocal(), withoutSuffix); +}
@@ -0,0 +1,55 @@
+import { normalizeUnits, normalizeObjectUnits } from '../units/aliases'; +import { getPrioritizedUnits } from '../units/priorities'; +import { hooks } from '../utils/hooks'; +import isFunction from '../utils/is-function'; + + +export function makeGetSet (unit, keepTime) { + return function (value) { + if (value != null) { + set(this, unit, value); + hooks.updateOffset(this, keepTime); + return this; + } else { + return get(this, unit); + } + }; +} + +export function get (mom, unit) { + return mom.isValid() ? + mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN; +} + +export function set (mom, unit, value) { + if (mom.isValid()) { + mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); + } +} + +// MOMENTS + +export function stringGet (units) { + units = normalizeUnits(units); + if (isFunction(this[units])) { + return this[units](); + } + return this; +} + + +export function stringSet (units, value) { + if (typeof units === 'object') { + units = normalizeObjectUnits(units); + var prioritized = getPrioritizedUnits(units); + for (var i = 0; i < prioritized.length; i++) { + this[prioritized[i].unit](units[prioritized[i].unit]); + } + } else { + units = normalizeUnits(units); + if (isFunction(this[units])) { + return this[units](value); + } + } + return this; +}
@@ -0,0 +1,34 @@
+import { getLocale } from '../locale/locales'; +import { deprecate } from '../utils/deprecate'; + +// If passed a locale key, it will set the locale for this +// instance. Otherwise, it will return the locale configuration +// variables for this instance. +export function locale (key) { + var newLocaleData; + + if (key === undefined) { + return this._locale._abbr; + } else { + newLocaleData = getLocale(key); + if (newLocaleData != null) { + this._locale = newLocaleData; + } + return this; + } +} + +export var lang = deprecate( + 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', + function (key) { + if (key === undefined) { + return this.localeData(); + } else { + return this.locale(key); + } + } +); + +export function localeData () { + return this._locale; +}
@@ -0,0 +1,63 @@
+import { deprecate } from '../utils/deprecate'; +import isArray from '../utils/is-array'; +import { createLocal } from '../create/local'; +import { createInvalid } from '../create/valid'; + +export var prototypeMin = deprecate( + 'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/', + function () { + var other = createLocal.apply(null, arguments); + if (this.isValid() && other.isValid()) { + return other < this ? this : other; + } else { + return createInvalid(); + } + } +); + +export var prototypeMax = deprecate( + 'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/', + function () { + var other = createLocal.apply(null, arguments); + if (this.isValid() && other.isValid()) { + return other > this ? this : other; + } else { + return createInvalid(); + } + } +); + +// Pick a moment m from moments so that m[fn](other) is true for all +// other. This relies on the function fn to be transitive. +// +// moments should either be an array of moment objects or an array, whose +// first element is an array of moment objects. +function pickBy(fn, moments) { + var res, i; + if (moments.length === 1 && isArray(moments[0])) { + moments = moments[0]; + } + if (!moments.length) { + return createLocal(); + } + res = moments[0]; + for (i = 1; i < moments.length; ++i) { + if (!moments[i].isValid() || moments[i][fn](res)) { + res = moments[i]; + } + } + return res; +} + +// TODO: Use [].sort instead? +export function min () { + var args = [].slice.call(arguments, 0); + + return pickBy('isBefore', args); +} + +export function max () { + var args = [].slice.call(arguments, 0); + + return pickBy('isAfter', args); +}
@@ -0,0 +1,28 @@
+import { createLocal } from '../create/local'; +import { createUTC } from '../create/utc'; +import { createInvalid } from '../create/valid'; +import { isMoment } from './constructor'; +import { min, max } from './min-max'; +import { now } from './now'; +import momentPrototype from './prototype'; + +function createUnix (input) { + return createLocal(input * 1000); +} + +function createInZone () { + return createLocal.apply(null, arguments).parseZone(); +} + +export { + now, + min, + max, + isMoment, + createUTC, + createUnix, + createLocal, + createInZone, + createInvalid, + momentPrototype +};
@@ -0,0 +1,3 @@
+export var now = function () { + return Date.now ? Date.now() : +(new Date()); +};
@@ -0,0 +1,149 @@
+import { Moment } from './constructor'; + +var proto = Moment.prototype; + +import { add, subtract } from './add-subtract'; +import { calendar, getCalendarFormat } from './calendar'; +import { clone } from './clone'; +import { isBefore, isBetween, isSame, isAfter, isSameOrAfter, isSameOrBefore } from './compare'; +import { diff } from './diff'; +import { format, toString, toISOString } from './format'; +import { from, fromNow } from './from'; +import { to, toNow } from './to'; +import { stringGet, stringSet } from './get-set'; +import { locale, localeData, lang } from './locale'; +import { prototypeMin, prototypeMax } from './min-max'; +import { startOf, endOf } from './start-end-of'; +import { valueOf, toDate, toArray, toObject, toJSON, unix } from './to-type'; +import { isValid, parsingFlags, invalidAt } from './valid'; +import { creationData } from './creation-data'; + +proto.add = add; +proto.calendar = calendar; +proto.clone = clone; +proto.diff = diff; +proto.endOf = endOf; +proto.format = format; +proto.from = from; +proto.fromNow = fromNow; +proto.to = to; +proto.toNow = toNow; +proto.get = stringGet; +proto.invalidAt = invalidAt; +proto.isAfter = isAfter; +proto.isBefore = isBefore; +proto.isBetween = isBetween; +proto.isSame = isSame; +proto.isSameOrAfter = isSameOrAfter; +proto.isSameOrBefore = isSameOrBefore; +proto.isValid = isValid; +proto.lang = lang; +proto.locale = locale; +proto.localeData = localeData; +proto.max = prototypeMax; +proto.min = prototypeMin; +proto.parsingFlags = parsingFlags; +proto.set = stringSet; +proto.startOf = startOf; +proto.subtract = subtract; +proto.toArray = toArray; +proto.toObject = toObject; +proto.toDate = toDate; +proto.toISOString = toISOString; +proto.toJSON = toJSON; +proto.toString = toString; +proto.unix = unix; +proto.valueOf = valueOf; +proto.creationData = creationData; + +// Year +import { getSetYear, getIsLeapYear } from '../units/year'; +proto.year = getSetYear; +proto.isLeapYear = getIsLeapYear; + +// Week Year +import { getSetWeekYear, getSetISOWeekYear, getWeeksInYear, getISOWeeksInYear } from '../units/week-year'; +proto.weekYear = getSetWeekYear; +proto.isoWeekYear = getSetISOWeekYear; + +// Quarter +import { getSetQuarter } from '../units/quarter'; +proto.quarter = proto.quarters = getSetQuarter; + +// Month +import { getSetMonth, getDaysInMonth } from '../units/month'; +proto.month = getSetMonth; +proto.daysInMonth = getDaysInMonth; + +// Week +import { getSetWeek, getSetISOWeek } from '../units/week'; +proto.week = proto.weeks = getSetWeek; +proto.isoWeek = proto.isoWeeks = getSetISOWeek; +proto.weeksInYear = getWeeksInYear; +proto.isoWeeksInYear = getISOWeeksInYear; + +// Day +import { getSetDayOfMonth } from '../units/day-of-month'; +import { getSetDayOfWeek, getSetISODayOfWeek, getSetLocaleDayOfWeek } from '../units/day-of-week'; +import { getSetDayOfYear } from '../units/day-of-year'; +proto.date = getSetDayOfMonth; +proto.day = proto.days = getSetDayOfWeek; +proto.weekday = getSetLocaleDayOfWeek; +proto.isoWeekday = getSetISODayOfWeek; +proto.dayOfYear = getSetDayOfYear; + +// Hour +import { getSetHour } from '../units/hour'; +proto.hour = proto.hours = getSetHour; + +// Minute +import { getSetMinute } from '../units/minute'; +proto.minute = proto.minutes = getSetMinute; + +// Second +import { getSetSecond } from '../units/second'; +proto.second = proto.seconds = getSetSecond; + +// Millisecond +import { getSetMillisecond } from '../units/millisecond'; +proto.millisecond = proto.milliseconds = getSetMillisecond; + +// Offset +import { + getSetOffset, + setOffsetToUTC, + setOffsetToLocal, + setOffsetToParsedOffset, + hasAlignedHourOffset, + isDaylightSavingTime, + isDaylightSavingTimeShifted, + getSetZone, + isLocal, + isUtcOffset, + isUtc +} from '../units/offset'; +proto.utcOffset = getSetOffset; +proto.utc = setOffsetToUTC; +proto.local = setOffsetToLocal; +proto.parseZone = setOffsetToParsedOffset; +proto.hasAlignedHourOffset = hasAlignedHourOffset; +proto.isDST = isDaylightSavingTime; +proto.isLocal = isLocal; +proto.isUtcOffset = isUtcOffset; +proto.isUtc = isUtc; +proto.isUTC = isUtc; + +// Timezone +import { getZoneAbbr, getZoneName } from '../units/timezone'; +proto.zoneAbbr = getZoneAbbr; +proto.zoneName = getZoneName; + +// Deprecations +import { deprecate } from '../utils/deprecate'; +proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth); +proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth); +proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear); +proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone); +proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted); + +export default proto;
@@ -0,0 +1,59 @@
+import { normalizeUnits } from '../units/aliases'; + +export function startOf (units) { + units = normalizeUnits(units); + // the following switch intentionally omits break keywords + // to utilize falling through the cases. + switch (units) { + case 'year': + this.month(0); + /* falls through */ + case 'quarter': + case 'month': + this.date(1); + /* falls through */ + case 'week': + case 'isoWeek': + case 'day': + case 'date': + this.hours(0); + /* falls through */ + case 'hour': + this.minutes(0); + /* falls through */ + case 'minute': + this.seconds(0); + /* falls through */ + case 'second': + this.milliseconds(0); + } + + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } + if (units === 'isoWeek') { + this.isoWeekday(1); + } + + // quarters are also special + if (units === 'quarter') { + this.month(Math.floor(this.month() / 3) * 3); + } + + return this; +} + +export function endOf (units) { + units = normalizeUnits(units); + if (units === undefined || units === 'millisecond') { + return this; + } + + // 'date' is an alias for 'day', so it should be considered as such. + if (units === 'date') { + units = 'day'; + } + + return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); +}
@@ -0,0 +1,34 @@
+export function valueOf () { + return this._d.valueOf() - ((this._offset || 0) * 60000); +} + +export function unix () { + return Math.floor(this.valueOf() / 1000); +} + +export function toDate () { + return new Date(this.valueOf()); +} + +export function toArray () { + var m = this; + return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()]; +} + +export function toObject () { + var m = this; + return { + years: m.year(), + months: m.month(), + date: m.date(), + hours: m.hours(), + minutes: m.minutes(), + seconds: m.seconds(), + milliseconds: m.milliseconds() + }; +} + +export function toJSON () { + // new Date(NaN).toJSON() === null + return this.isValid() ? this.toISOString() : null; +}
@@ -0,0 +1,17 @@
+import { createDuration } from '../duration/create'; +import { createLocal } from '../create/local'; +import { isMoment } from '../moment/constructor'; + +export function to (time, withoutSuffix) { + if (this.isValid() && + ((isMoment(time) && time.isValid()) || + createLocal(time).isValid())) { + return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix); + } else { + return this.localeData().invalidDate(); + } +} + +export function toNow (withoutSuffix) { + return this.to(createLocal(), withoutSuffix); +}
@@ -0,0 +1,15 @@
+import { isValid as _isValid } from '../create/valid'; +import extend from '../utils/extend'; +import getParsingFlags from '../create/parsing-flags'; + +export function isValid () { + return _isValid(this); +} + +export function parsingFlags () { + return extend({}, getParsingFlags(this)); +} + +export function invalidAt () { + return getParsingFlags(this).overflow; +}
@@ -0,0 +1,54 @@
+export var match1 = /\d/; // 0 - 9 +export var match2 = /\d\d/; // 00 - 99 +export var match3 = /\d{3}/; // 000 - 999 +export var match4 = /\d{4}/; // 0000 - 9999 +export var match6 = /[+-]?\d{6}/; // -999999 - 999999 +export var match1to2 = /\d\d?/; // 0 - 99 +export var match3to4 = /\d\d\d\d?/; // 999 - 9999 +export var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999 +export var match1to3 = /\d{1,3}/; // 0 - 999 +export var match1to4 = /\d{1,4}/; // 0 - 9999 +export var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999 + +export var matchUnsigned = /\d+/; // 0 - inf +export var matchSigned = /[+-]?\d+/; // -inf - inf + +export var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z +export var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z + +export var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123 + +// any word (or two) characters or numbers including two/three word month in arabic. +// includes scottish gaelic two word and hyphenated months +export var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i; + + +import hasOwnProp from '../utils/has-own-prop'; +import isFunction from '../utils/is-function'; + +var regexes = {}; + +export function addRegexToken (token, regex, strictRegex) { + regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) { + return (isStrict && strictRegex) ? strictRegex : regex; + }; +} + +export function getParseRegexForToken (token, config) { + if (!hasOwnProp(regexes, token)) { + return new RegExp(unescapeFormat(token)); + } + + return regexes[token](config._strict, config._locale); +} + +// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript +function unescapeFormat(s) { + return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + })); +} + +export function regexEscape(s) { + return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); +}
@@ -0,0 +1,32 @@
+import hasOwnProp from '../utils/has-own-prop'; +import toInt from '../utils/to-int'; + +var tokens = {}; + +export function addParseToken (token, callback) { + var i, func = callback; + if (typeof token === 'string') { + token = [token]; + } + if (typeof callback === 'number') { + func = function (input, array) { + array[callback] = toInt(input); + }; + } + for (i = 0; i < token.length; i++) { + tokens[token[i]] = func; + } +} + +export function addWeekParseToken (token, callback) { + addParseToken(token, function (input, array, config, token) { + config._w = config._w || {}; + callback(input, config._w, config, token); + }); +} + +export function addTimeToArrayFromToken(token, input, config) { + if (input != null && hasOwnProp(tokens, token)) { + tokens[token](input, config._a, config, token); + } +}
@@ -0,0 +1,30 @@
+import hasOwnProp from '../utils/has-own-prop'; + +var aliases = {}; + +export function addUnitAlias (unit, shorthand) { + var lowerCase = unit.toLowerCase(); + aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit; +} + +export function normalizeUnits(units) { + return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined; +} + +export function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; + + for (prop in inputObject) { + if (hasOwnProp(inputObject, prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } + + return normalizedInput; +} +
@@ -0,0 +1,9 @@
+export var YEAR = 0; +export var MONTH = 1; +export var DATE = 2; +export var HOUR = 3; +export var MINUTE = 4; +export var SECOND = 5; +export var MILLISECOND = 6; +export var WEEK = 7; +export var WEEKDAY = 8;
@@ -0,0 +1,36 @@
+import { makeGetSet } from '../moment/get-set'; +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addUnitPriority } from './priorities'; +import { addRegexToken, match1to2, match2 } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { DATE } from './constants'; +import toInt from '../utils/to-int'; + +// FORMATTING + +addFormatToken('D', ['DD', 2], 'Do', 'date'); + +// ALIASES + +addUnitAlias('date', 'D'); + +// PRIOROITY +addUnitPriority('date', 9); + +// PARSING + +addRegexToken('D', match1to2); +addRegexToken('DD', match1to2, match2); +addRegexToken('Do', function (isStrict, locale) { + return isStrict ? locale._ordinalParse : locale._ordinalParseLenient; +}); + +addParseToken(['D', 'DD'], DATE); +addParseToken('Do', function (input, array) { + array[DATE] = toInt(input.match(match1to2)[0], 10); +}); + +// MOMENTS + +export var getSetDayOfMonth = makeGetSet('Date', true);
@@ -0,0 +1,360 @@
+import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addUnitPriority } from './priorities'; +import { addRegexToken, match1to2, matchWord, regexEscape } from '../parse/regex'; +import { addWeekParseToken } from '../parse/token'; +import toInt from '../utils/to-int'; +import isArray from '../utils/is-array'; +import indexOf from '../utils/index-of'; +import hasOwnProp from '../utils/has-own-prop'; +import { createUTC } from '../create/utc'; +import getParsingFlags from '../create/parsing-flags'; + +// FORMATTING + +addFormatToken('d', 0, 'do', 'day'); + +addFormatToken('dd', 0, 0, function (format) { + return this.localeData().weekdaysMin(this, format); +}); + +addFormatToken('ddd', 0, 0, function (format) { + return this.localeData().weekdaysShort(this, format); +}); + +addFormatToken('dddd', 0, 0, function (format) { + return this.localeData().weekdays(this, format); +}); + +addFormatToken('e', 0, 0, 'weekday'); +addFormatToken('E', 0, 0, 'isoWeekday'); + +// ALIASES + +addUnitAlias('day', 'd'); +addUnitAlias('weekday', 'e'); +addUnitAlias('isoWeekday', 'E'); + +// PRIORITY +addUnitPriority('day', 11); +addUnitPriority('weekday', 11); +addUnitPriority('isoWeekday', 11); + +// PARSING + +addRegexToken('d', match1to2); +addRegexToken('e', match1to2); +addRegexToken('E', match1to2); +addRegexToken('dd', function (isStrict, locale) { + return locale.weekdaysMinRegex(isStrict); +}); +addRegexToken('ddd', function (isStrict, locale) { + return locale.weekdaysShortRegex(isStrict); +}); +addRegexToken('dddd', function (isStrict, locale) { + return locale.weekdaysRegex(isStrict); +}); + +addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) { + var weekday = config._locale.weekdaysParse(input, token, config._strict); + // if we didn't get a weekday name, mark the date as invalid + if (weekday != null) { + week.d = weekday; + } else { + getParsingFlags(config).invalidWeekday = input; + } +}); + +addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) { + week[token] = toInt(input); +}); + +// HELPERS + +function parseWeekday(input, locale) { + if (typeof input !== 'string') { + return input; + } + + if (!isNaN(input)) { + return parseInt(input, 10); + } + + input = locale.weekdaysParse(input); + if (typeof input === 'number') { + return input; + } + + return null; +} + +function parseIsoWeekday(input, locale) { + if (typeof input === 'string') { + return locale.weekdaysParse(input) % 7 || 7; + } + return isNaN(input) ? null : input; +} + +// LOCALES + +export var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'); +export function localeWeekdays (m, format) { + return isArray(this._weekdays) ? this._weekdays[m.day()] : + this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()]; +} + +export var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'); +export function localeWeekdaysShort (m) { + return this._weekdaysShort[m.day()]; +} + +export var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'); +export function localeWeekdaysMin (m) { + return this._weekdaysMin[m.day()]; +} + +function handleStrictParse(weekdayName, format, strict) { + var i, ii, mom, llc = weekdayName.toLocaleLowerCase(); + if (!this._weekdaysParse) { + this._weekdaysParse = []; + this._shortWeekdaysParse = []; + this._minWeekdaysParse = []; + + for (i = 0; i < 7; ++i) { + mom = createUTC([2000, 1]).day(i); + this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase(); + this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase(); + this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase(); + } + } + + if (strict) { + if (format === 'dddd') { + ii = indexOf.call(this._weekdaysParse, llc); + return ii !== -1 ? ii : null; + } else if (format === 'ddd') { + ii = indexOf.call(this._shortWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } + } else { + if (format === 'dddd') { + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else if (format === 'ddd') { + ii = indexOf.call(this._shortWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._minWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._minWeekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._weekdaysParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortWeekdaysParse, llc); + return ii !== -1 ? ii : null; + } + } +} + +export function localeWeekdaysParse (weekdayName, format, strict) { + var i, mom, regex; + + if (this._weekdaysParseExact) { + return handleStrictParse.call(this, weekdayName, format, strict); + } + + if (!this._weekdaysParse) { + this._weekdaysParse = []; + this._minWeekdaysParse = []; + this._shortWeekdaysParse = []; + this._fullWeekdaysParse = []; + } + + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + + mom = createUTC([2000, 1]).day(i); + if (strict && !this._fullWeekdaysParse[i]) { + this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i'); + this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i'); + this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i'); + } + if (!this._weekdaysParse[i]) { + regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); + this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) { + return i; + } else if (!strict && this._weekdaysParse[i].test(weekdayName)) { + return i; + } + } +} + +// MOMENTS + +export function getSetDayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + input = parseWeekday(input, this.localeData()); + return this.add(input - day, 'd'); + } else { + return day; + } +} + +export function getSetLocaleDayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; + return input == null ? weekday : this.add(input - weekday, 'd'); +} + +export function getSetISODayOfWeek (input) { + if (!this.isValid()) { + return input != null ? this : NaN; + } + + // behaves the same as moment#day except + // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) + // as a setter, sunday should belong to the previous week. + + if (input != null) { + var weekday = parseIsoWeekday(input, this.localeData()); + return this.day(this.day() % 7 ? weekday : weekday - 7); + } else { + return this.day() || 7; + } +} + +var defaultWeekdaysRegex = matchWord; +export function weekdaysRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysStrictRegex; + } else { + return this._weekdaysRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysRegex')) { + this._weekdaysRegex = defaultWeekdaysRegex; + } + return this._weekdaysStrictRegex && isStrict ? + this._weekdaysStrictRegex : this._weekdaysRegex; + } +} + +var defaultWeekdaysShortRegex = matchWord; +export function weekdaysShortRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysShortStrictRegex; + } else { + return this._weekdaysShortRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysShortRegex')) { + this._weekdaysShortRegex = defaultWeekdaysShortRegex; + } + return this._weekdaysShortStrictRegex && isStrict ? + this._weekdaysShortStrictRegex : this._weekdaysShortRegex; + } +} + +var defaultWeekdaysMinRegex = matchWord; +export function weekdaysMinRegex (isStrict) { + if (this._weekdaysParseExact) { + if (!hasOwnProp(this, '_weekdaysRegex')) { + computeWeekdaysParse.call(this); + } + if (isStrict) { + return this._weekdaysMinStrictRegex; + } else { + return this._weekdaysMinRegex; + } + } else { + if (!hasOwnProp(this, '_weekdaysMinRegex')) { + this._weekdaysMinRegex = defaultWeekdaysMinRegex; + } + return this._weekdaysMinStrictRegex && isStrict ? + this._weekdaysMinStrictRegex : this._weekdaysMinRegex; + } +} + + +function computeWeekdaysParse () { + function cmpLenRev(a, b) { + return b.length - a.length; + } + + var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [], + i, mom, minp, shortp, longp; + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + mom = createUTC([2000, 1]).day(i); + minp = this.weekdaysMin(mom, ''); + shortp = this.weekdaysShort(mom, ''); + longp = this.weekdays(mom, ''); + minPieces.push(minp); + shortPieces.push(shortp); + longPieces.push(longp); + mixedPieces.push(minp); + mixedPieces.push(shortp); + mixedPieces.push(longp); + } + // Sorting makes sure if one weekday (or abbr) is a prefix of another it + // will match the longer piece. + minPieces.sort(cmpLenRev); + shortPieces.sort(cmpLenRev); + longPieces.sort(cmpLenRev); + mixedPieces.sort(cmpLenRev); + for (i = 0; i < 7; i++) { + shortPieces[i] = regexEscape(shortPieces[i]); + longPieces[i] = regexEscape(longPieces[i]); + mixedPieces[i] = regexEscape(mixedPieces[i]); + } + + this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); + this._weekdaysShortRegex = this._weekdaysRegex; + this._weekdaysMinRegex = this._weekdaysRegex; + + this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); + this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); + this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i'); +}
@@ -0,0 +1,36 @@
+import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addUnitPriority } from './priorities'; +import { addRegexToken, match3, match1to3 } from '../parse/regex'; +import { daysInYear } from './year'; +import { createUTCDate } from '../create/date-from-array'; +import { addParseToken } from '../parse/token'; +import toInt from '../utils/to-int'; + +// FORMATTING + +addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); + +// ALIASES + +addUnitAlias('dayOfYear', 'DDD'); + +// PRIORITY +addUnitPriority('dayOfYear', 4); + +// PARSING + +addRegexToken('DDD', match1to3); +addRegexToken('DDDD', match3); +addParseToken(['DDD', 'DDDD'], function (input, array, config) { + config._dayOfYear = toInt(input); +}); + +// HELPERS + +// MOMENTS + +export function getSetDayOfYear (input) { + var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); +}
@@ -0,0 +1,138 @@
+import { makeGetSet } from '../moment/get-set'; +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addUnitPriority } from './priorities'; +import { addRegexToken, match1to2, match2, match3to4, match5to6 } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { HOUR, MINUTE, SECOND } from './constants'; +import toInt from '../utils/to-int'; +import zeroFill from '../utils/zero-fill'; +import getParsingFlags from '../create/parsing-flags'; + +// FORMATTING + +function hFormat() { + return this.hours() % 12 || 12; +} + +function kFormat() { + return this.hours() || 24; +} + +addFormatToken('H', ['HH', 2], 0, 'hour'); +addFormatToken('h', ['hh', 2], 0, hFormat); +addFormatToken('k', ['kk', 2], 0, kFormat); + +addFormatToken('hmm', 0, 0, function () { + return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2); +}); + +addFormatToken('hmmss', 0, 0, function () { + return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) + + zeroFill(this.seconds(), 2); +}); + +addFormatToken('Hmm', 0, 0, function () { + return '' + this.hours() + zeroFill(this.minutes(), 2); +}); + +addFormatToken('Hmmss', 0, 0, function () { + return '' + this.hours() + zeroFill(this.minutes(), 2) + + zeroFill(this.seconds(), 2); +}); + +function meridiem (token, lowercase) { + addFormatToken(token, 0, 0, function () { + return this.localeData().meridiem(this.hours(), this.minutes(), lowercase); + }); +} + +meridiem('a', true); +meridiem('A', false); + +// ALIASES + +addUnitAlias('hour', 'h'); + +// PRIORITY +addUnitPriority('hour', 13); + +// PARSING + +function matchMeridiem (isStrict, locale) { + return locale._meridiemParse; +} + +addRegexToken('a', matchMeridiem); +addRegexToken('A', matchMeridiem); +addRegexToken('H', match1to2); +addRegexToken('h', match1to2); +addRegexToken('HH', match1to2, match2); +addRegexToken('hh', match1to2, match2); + +addRegexToken('hmm', match3to4); +addRegexToken('hmmss', match5to6); +addRegexToken('Hmm', match3to4); +addRegexToken('Hmmss', match5to6); + +addParseToken(['H', 'HH'], HOUR); +addParseToken(['a', 'A'], function (input, array, config) { + config._isPm = config._locale.isPM(input); + config._meridiem = input; +}); +addParseToken(['h', 'hh'], function (input, array, config) { + array[HOUR] = toInt(input); + getParsingFlags(config).bigHour = true; +}); +addParseToken('hmm', function (input, array, config) { + var pos = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos)); + array[MINUTE] = toInt(input.substr(pos)); + getParsingFlags(config).bigHour = true; +}); +addParseToken('hmmss', function (input, array, config) { + var pos1 = input.length - 4; + var pos2 = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos1)); + array[MINUTE] = toInt(input.substr(pos1, 2)); + array[SECOND] = toInt(input.substr(pos2)); + getParsingFlags(config).bigHour = true; +}); +addParseToken('Hmm', function (input, array, config) { + var pos = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos)); + array[MINUTE] = toInt(input.substr(pos)); +}); +addParseToken('Hmmss', function (input, array, config) { + var pos1 = input.length - 4; + var pos2 = input.length - 2; + array[HOUR] = toInt(input.substr(0, pos1)); + array[MINUTE] = toInt(input.substr(pos1, 2)); + array[SECOND] = toInt(input.substr(pos2)); +}); + +// LOCALES + +export function localeIsPM (input) { + // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays + // Using charAt should be more compatible. + return ((input + '').toLowerCase().charAt(0) === 'p'); +} + +export var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i; +export function localeMeridiem (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } +} + + +// MOMENTS + +// Setting the hour should keep the time, because the user explicitly +// specified which hour he wants. So trying to maintain the same hour (in +// a new timezone) makes sense. Adding/subtracting hours does not follow +// this rule. +export var getSetHour = makeGetSet('Hours', true);
@@ -0,0 +1,69 @@
+import { makeGetSet } from '../moment/get-set'; +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addUnitPriority } from './priorities'; +import { addRegexToken, match1, match2, match3, match1to3, matchUnsigned } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { MILLISECOND } from './constants'; +import toInt from '../utils/to-int'; + +// FORMATTING + +addFormatToken('S', 0, 0, function () { + return ~~(this.millisecond() / 100); +}); + +addFormatToken(0, ['SS', 2], 0, function () { + return ~~(this.millisecond() / 10); +}); + +addFormatToken(0, ['SSS', 3], 0, 'millisecond'); +addFormatToken(0, ['SSSS', 4], 0, function () { + return this.millisecond() * 10; +}); +addFormatToken(0, ['SSSSS', 5], 0, function () { + return this.millisecond() * 100; +}); +addFormatToken(0, ['SSSSSS', 6], 0, function () { + return this.millisecond() * 1000; +}); +addFormatToken(0, ['SSSSSSS', 7], 0, function () { + return this.millisecond() * 10000; +}); +addFormatToken(0, ['SSSSSSSS', 8], 0, function () { + return this.millisecond() * 100000; +}); +addFormatToken(0, ['SSSSSSSSS', 9], 0, function () { + return this.millisecond() * 1000000; +}); + + +// ALIASES + +addUnitAlias('millisecond', 'ms'); + +// PRIORITY + +addUnitPriority('millisecond', 16); + +// PARSING + +addRegexToken('S', match1to3, match1); +addRegexToken('SS', match1to3, match2); +addRegexToken('SSS', match1to3, match3); + +var token; +for (token = 'SSSS'; token.length <= 9; token += 'S') { + addRegexToken(token, matchUnsigned); +} + +function parseMs(input, array) { + array[MILLISECOND] = toInt(('0.' + input) * 1000); +} + +for (token = 'S'; token.length <= 9; token += 'S') { + addParseToken(token, parseMs); +} +// MOMENTS + +export var getSetMillisecond = makeGetSet('Milliseconds', false);
@@ -0,0 +1,29 @@
+import { makeGetSet } from '../moment/get-set'; +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addUnitPriority } from './priorities'; +import { addRegexToken, match1to2, match2 } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { MINUTE } from './constants'; + +// FORMATTING + +addFormatToken('m', ['mm', 2], 0, 'minute'); + +// ALIASES + +addUnitAlias('minute', 'm'); + +// PRIORITY + +addUnitPriority('minute', 14); + +// PARSING + +addRegexToken('m', match1to2); +addRegexToken('mm', match1to2, match2); +addParseToken(['m', 'mm'], MINUTE); + +// MOMENTS + +export var getSetMinute = makeGetSet('Minutes', false);
@@ -0,0 +1,274 @@
+import { get } from '../moment/get-set'; +import hasOwnProp from '../utils/has-own-prop'; +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addUnitPriority } from './priorities'; +import { addRegexToken, match1to2, match2, matchWord, regexEscape } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { hooks } from '../utils/hooks'; +import { MONTH } from './constants'; +import toInt from '../utils/to-int'; +import isArray from '../utils/is-array'; +import indexOf from '../utils/index-of'; +import { createUTC } from '../create/utc'; +import getParsingFlags from '../create/parsing-flags'; + +export function daysInMonth(year, month) { + return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); +} + +// FORMATTING + +addFormatToken('M', ['MM', 2], 'Mo', function () { + return this.month() + 1; +}); + +addFormatToken('MMM', 0, 0, function (format) { + return this.localeData().monthsShort(this, format); +}); + +addFormatToken('MMMM', 0, 0, function (format) { + return this.localeData().months(this, format); +}); + +// ALIASES + +addUnitAlias('month', 'M'); + +// PRIORITY + +addUnitPriority('month', 8); + +// PARSING + +addRegexToken('M', match1to2); +addRegexToken('MM', match1to2, match2); +addRegexToken('MMM', function (isStrict, locale) { + return locale.monthsShortRegex(isStrict); +}); +addRegexToken('MMMM', function (isStrict, locale) { + return locale.monthsRegex(isStrict); +}); + +addParseToken(['M', 'MM'], function (input, array) { + array[MONTH] = toInt(input) - 1; +}); + +addParseToken(['MMM', 'MMMM'], function (input, array, config, token) { + var month = config._locale.monthsParse(input, token, config._strict); + // if we didn't find a month name, mark the date as invalid. + if (month != null) { + array[MONTH] = month; + } else { + getParsingFlags(config).invalidMonth = input; + } +}); + +// LOCALES + +var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/; +export var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'); +export function localeMonths (m, format) { + return isArray(this._months) ? this._months[m.month()] : + this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()]; +} + +export var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'); +export function localeMonthsShort (m, format) { + return isArray(this._monthsShort) ? this._monthsShort[m.month()] : + this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()]; +} + +function handleStrictParse(monthName, format, strict) { + var i, ii, mom, llc = monthName.toLocaleLowerCase(); + if (!this._monthsParse) { + // this is not used + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + for (i = 0; i < 12; ++i) { + mom = createUTC([2000, i]); + this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase(); + this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase(); + } + } + + if (strict) { + if (format === 'MMM') { + ii = indexOf.call(this._shortMonthsParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._longMonthsParse, llc); + return ii !== -1 ? ii : null; + } + } else { + if (format === 'MMM') { + ii = indexOf.call(this._shortMonthsParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._longMonthsParse, llc); + return ii !== -1 ? ii : null; + } else { + ii = indexOf.call(this._longMonthsParse, llc); + if (ii !== -1) { + return ii; + } + ii = indexOf.call(this._shortMonthsParse, llc); + return ii !== -1 ? ii : null; + } + } +} + +export function localeMonthsParse (monthName, format, strict) { + var i, mom, regex; + + if (this._monthsParseExact) { + return handleStrictParse.call(this, monthName, format, strict); + } + + if (!this._monthsParse) { + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + } + + // TODO: add sorting + // Sorting makes sure if one month (or abbr) is a prefix of another + // see sorting in computeMonthsParse + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = createUTC([2000, i]); + if (strict && !this._longMonthsParse[i]) { + this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i'); + this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i'); + } + if (!strict && !this._monthsParse[i]) { + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) { + return i; + } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) { + return i; + } else if (!strict && this._monthsParse[i].test(monthName)) { + return i; + } + } +} + +// MOMENTS + +export function setMonth (mom, value) { + var dayOfMonth; + + if (!mom.isValid()) { + // No op + return mom; + } + + if (typeof value === 'string') { + if (/^\d+$/.test(value)) { + value = toInt(value); + } else { + value = mom.localeData().monthsParse(value); + // TODO: Another silent failure? + if (typeof value !== 'number') { + return mom; + } + } + } + + dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value)); + mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); + return mom; +} + +export function getSetMonth (value) { + if (value != null) { + setMonth(this, value); + hooks.updateOffset(this, true); + return this; + } else { + return get(this, 'Month'); + } +} + +export function getDaysInMonth () { + return daysInMonth(this.year(), this.month()); +} + +var defaultMonthsShortRegex = matchWord; +export function monthsShortRegex (isStrict) { + if (this._monthsParseExact) { + if (!hasOwnProp(this, '_monthsRegex')) { + computeMonthsParse.call(this); + } + if (isStrict) { + return this._monthsShortStrictRegex; + } else { + return this._monthsShortRegex; + } + } else { + if (!hasOwnProp(this, '_monthsShortRegex')) { + this._monthsShortRegex = defaultMonthsShortRegex; + } + return this._monthsShortStrictRegex && isStrict ? + this._monthsShortStrictRegex : this._monthsShortRegex; + } +} + +var defaultMonthsRegex = matchWord; +export function monthsRegex (isStrict) { + if (this._monthsParseExact) { + if (!hasOwnProp(this, '_monthsRegex')) { + computeMonthsParse.call(this); + } + if (isStrict) { + return this._monthsStrictRegex; + } else { + return this._monthsRegex; + } + } else { + if (!hasOwnProp(this, '_monthsRegex')) { + this._monthsRegex = defaultMonthsRegex; + } + return this._monthsStrictRegex && isStrict ? + this._monthsStrictRegex : this._monthsRegex; + } +} + +function computeMonthsParse () { + function cmpLenRev(a, b) { + return b.length - a.length; + } + + var shortPieces = [], longPieces = [], mixedPieces = [], + i, mom; + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = createUTC([2000, i]); + shortPieces.push(this.monthsShort(mom, '')); + longPieces.push(this.months(mom, '')); + mixedPieces.push(this.months(mom, '')); + mixedPieces.push(this.monthsShort(mom, '')); + } + // Sorting makes sure if one month (or abbr) is a prefix of another it + // will match the longer piece. + shortPieces.sort(cmpLenRev); + longPieces.sort(cmpLenRev); + mixedPieces.sort(cmpLenRev); + for (i = 0; i < 12; i++) { + shortPieces[i] = regexEscape(shortPieces[i]); + longPieces[i] = regexEscape(longPieces[i]); + } + for (i = 0; i < 24; i++) { + mixedPieces[i] = regexEscape(mixedPieces[i]); + } + + this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); + this._monthsShortRegex = this._monthsRegex; + this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); + this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); +}
@@ -0,0 +1,219 @@
+import zeroFill from '../utils/zero-fill'; +import { createDuration } from '../duration/create'; +import { addSubtract } from '../moment/add-subtract'; +import { isMoment, copyConfig } from '../moment/constructor'; +import { addFormatToken } from '../format/format'; +import { addRegexToken, matchOffset, matchShortOffset } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { createLocal } from '../create/local'; +import { prepareConfig } from '../create/from-anything'; +import { createUTC } from '../create/utc'; +import isDate from '../utils/is-date'; +import toInt from '../utils/to-int'; +import isUndefined from '../utils/is-undefined'; +import compareArrays from '../utils/compare-arrays'; +import { hooks } from '../utils/hooks'; + +// FORMATTING + +function offset (token, separator) { + addFormatToken(token, 0, 0, function () { + var offset = this.utcOffset(); + var sign = '+'; + if (offset < 0) { + offset = -offset; + sign = '-'; + } + return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2); + }); +} + +offset('Z', ':'); +offset('ZZ', ''); + +// PARSING + +addRegexToken('Z', matchShortOffset); +addRegexToken('ZZ', matchShortOffset); +addParseToken(['Z', 'ZZ'], function (input, array, config) { + config._useUTC = true; + config._tzm = offsetFromString(matchShortOffset, input); +}); + +// HELPERS + +// timezone chunker +// '+10:00' > ['10', '00'] +// '-1530' > ['-15', '30'] +var chunkOffset = /([\+\-]|\d\d)/gi; + +function offsetFromString(matcher, string) { + var matches = ((string || '').match(matcher) || []); + var chunk = matches[matches.length - 1] || []; + var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0]; + var minutes = +(parts[1] * 60) + toInt(parts[2]); + + return parts[0] === '+' ? minutes : -minutes; +} + +// Return a moment from input, that is local/utc/zone equivalent to model. +export function cloneWithOffset(input, model) { + var res, diff; + if (model._isUTC) { + res = model.clone(); + diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf(); + // Use low-level api, because this fn is low-level api. + res._d.setTime(res._d.valueOf() + diff); + hooks.updateOffset(res, false); + return res; + } else { + return createLocal(input).local(); + } +} + +function getDateOffset (m) { + // On Firefox.24 Date#getTimezoneOffset returns a floating point. + // https://github.com/moment/moment/pull/1871 + return -Math.round(m._d.getTimezoneOffset() / 15) * 15; +} + +// HOOKS + +// This function will be called whenever a moment is mutated. +// It is intended to keep the offset in sync with the timezone. +hooks.updateOffset = function () {}; + +// MOMENTS + +// keepLocalTime = true means only change the timezone, without +// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> +// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset +// +0200, so we adjust the time as needed, to be valid. +// +// Keeping the time actually adds/subtracts (one hour) +// from the actual represented time. That is why we call updateOffset +// a second time. In case it wants us to change the offset again +// _changeInProgress == true case, then we have to adjust, because +// there is no such time in the given timezone. +export function getSetOffset (input, keepLocalTime) { + var offset = this._offset || 0, + localAdjust; + if (!this.isValid()) { + return input != null ? this : NaN; + } + if (input != null) { + if (typeof input === 'string') { + input = offsetFromString(matchShortOffset, input); + } else if (Math.abs(input) < 16) { + input = input * 60; + } + if (!this._isUTC && keepLocalTime) { + localAdjust = getDateOffset(this); + } + this._offset = input; + this._isUTC = true; + if (localAdjust != null) { + this.add(localAdjust, 'm'); + } + if (offset !== input) { + if (!keepLocalTime || this._changeInProgress) { + addSubtract(this, createDuration(input - offset, 'm'), 1, false); + } else if (!this._changeInProgress) { + this._changeInProgress = true; + hooks.updateOffset(this, true); + this._changeInProgress = null; + } + } + return this; + } else { + return this._isUTC ? offset : getDateOffset(this); + } +} + +export function getSetZone (input, keepLocalTime) { + if (input != null) { + if (typeof input !== 'string') { + input = -input; + } + + this.utcOffset(input, keepLocalTime); + + return this; + } else { + return -this.utcOffset(); + } +} + +export function setOffsetToUTC (keepLocalTime) { + return this.utcOffset(0, keepLocalTime); +} + +export function setOffsetToLocal (keepLocalTime) { + if (this._isUTC) { + this.utcOffset(0, keepLocalTime); + this._isUTC = false; + + if (keepLocalTime) { + this.subtract(getDateOffset(this), 'm'); + } + } + return this; +} + +export function setOffsetToParsedOffset () { + if (this._tzm) { + this.utcOffset(this._tzm); + } else if (typeof this._i === 'string') { + this.utcOffset(offsetFromString(matchOffset, this._i)); + } + return this; +} + +export function hasAlignedHourOffset (input) { + if (!this.isValid()) { + return false; + } + input = input ? createLocal(input).utcOffset() : 0; + + return (this.utcOffset() - input) % 60 === 0; +} + +export function isDaylightSavingTime () { + return ( + this.utcOffset() > this.clone().month(0).utcOffset() || + this.utcOffset() > this.clone().month(5).utcOffset() + ); +} + +export function isDaylightSavingTimeShifted () { + if (!isUndefined(this._isDSTShifted)) { + return this._isDSTShifted; + } + + var c = {}; + + copyConfig(c, this); + c = prepareConfig(c); + + if (c._a) { + var other = c._isUTC ? createUTC(c._a) : createLocal(c._a); + this._isDSTShifted = this.isValid() && + compareArrays(c._a, other.toArray()) > 0; + } else { + this._isDSTShifted = false; + } + + return this._isDSTShifted; +} + +export function isLocal () { + return this.isValid() ? !this._isUTC : false; +} + +export function isUtcOffset () { + return this.isValid() ? this._isUTC : false; +} + +export function isUtc () { + return this.isValid() ? this._isUTC && this._offset === 0 : false; +}
@@ -0,0 +1,16 @@
+var priorities = {}; + +export function addUnitPriority(unit, priority) { + priorities[unit] = priority; +} + +export function getPrioritizedUnits(unitsObj) { + var units = []; + for (var u in unitsObj) { + units.push({unit: u, priority: priorities[u]}); + } + units.sort(function (a, b) { + return a.priority - b.priority; + }); + return units; +}
@@ -0,0 +1,32 @@
+import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addUnitPriority } from './priorities'; +import { addRegexToken, match1 } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { MONTH } from './constants'; +import toInt from '../utils/to-int'; + +// FORMATTING + +addFormatToken('Q', 0, 'Qo', 'quarter'); + +// ALIASES + +addUnitAlias('quarter', 'Q'); + +// PRIORITY + +addUnitPriority('quarter', 7); + +// PARSING + +addRegexToken('Q', match1); +addParseToken('Q', function (input, array) { + array[MONTH] = (toInt(input) - 1) * 3; +}); + +// MOMENTS + +export function getSetQuarter (input) { + return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); +}
@@ -0,0 +1,29 @@
+import { makeGetSet } from '../moment/get-set'; +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addUnitPriority } from './priorities'; +import { addRegexToken, match1to2, match2 } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { SECOND } from './constants'; + +// FORMATTING + +addFormatToken('s', ['ss', 2], 0, 'second'); + +// ALIASES + +addUnitAlias('second', 's'); + +// PRIORITY + +addUnitPriority('second', 15); + +// PARSING + +addRegexToken('s', match1to2); +addRegexToken('ss', match1to2, match2); +addParseToken(['s', 'ss'], SECOND); + +// MOMENTS + +export var getSetSecond = makeGetSet('Seconds', false);
@@ -0,0 +1,20 @@
+import { addFormatToken } from '../format/format'; +import { addRegexToken, matchTimestamp, matchSigned } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import toInt from '../utils/to-int'; + +// FORMATTING + +addFormatToken('X', 0, 0, 'unix'); +addFormatToken('x', 0, 0, 'valueOf'); + +// PARSING + +addRegexToken('x', matchSigned); +addRegexToken('X', matchTimestamp); +addParseToken('X', function (input, array, config) { + config._d = new Date(parseFloat(input, 10) * 1000); +}); +addParseToken('x', function (input, array, config) { + config._d = new Date(toInt(input)); +});
@@ -0,0 +1,16 @@
+import { addFormatToken } from '../format/format'; + +// FORMATTING + +addFormatToken('z', 0, 0, 'zoneAbbr'); +addFormatToken('zz', 0, 0, 'zoneName'); + +// MOMENTS + +export function getZoneAbbr () { + return this._isUTC ? 'UTC' : ''; +} + +export function getZoneName () { + return this._isUTC ? 'Coordinated Universal Time' : ''; +}
@@ -0,0 +1,20 @@
+// Side effect imports +import './day-of-month'; +import './day-of-week'; +import './day-of-year'; +import './hour'; +import './millisecond'; +import './minute'; +import './month'; +import './offset'; +import './quarter'; +import './second'; +import './timestamp'; +import './timezone'; +import './week-year'; +import './week'; +import './year'; + +import { normalizeUnits } from './aliases'; + +export { normalizeUnits };
@@ -0,0 +1,65 @@
+import { daysInYear } from './year'; +import { createLocal } from '../create/local'; +import { createUTCDate } from '../create/date-from-array'; + +// start-of-first-week - start-of-year +function firstWeekOffset(year, dow, doy) { + var // first-week day -- which january is always in the first week (4 for iso, 1 for other) + fwd = 7 + dow - doy, + // first-week day local weekday -- which local weekday is fwd + fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7; + + return -fwdlw + fwd - 1; +} + +//http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday +export function dayOfYearFromWeeks(year, week, weekday, dow, doy) { + var localWeekday = (7 + weekday - dow) % 7, + weekOffset = firstWeekOffset(year, dow, doy), + dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset, + resYear, resDayOfYear; + + if (dayOfYear <= 0) { + resYear = year - 1; + resDayOfYear = daysInYear(resYear) + dayOfYear; + } else if (dayOfYear > daysInYear(year)) { + resYear = year + 1; + resDayOfYear = dayOfYear - daysInYear(year); + } else { + resYear = year; + resDayOfYear = dayOfYear; + } + + return { + year: resYear, + dayOfYear: resDayOfYear + }; +} + +export function weekOfYear(mom, dow, doy) { + var weekOffset = firstWeekOffset(mom.year(), dow, doy), + week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1, + resWeek, resYear; + + if (week < 1) { + resYear = mom.year() - 1; + resWeek = week + weeksInYear(resYear, dow, doy); + } else if (week > weeksInYear(mom.year(), dow, doy)) { + resWeek = week - weeksInYear(mom.year(), dow, doy); + resYear = mom.year() + 1; + } else { + resYear = mom.year(); + resWeek = week; + } + + return { + week: resWeek, + year: resYear + }; +} + +export function weeksInYear(year, dow, doy) { + var weekOffset = firstWeekOffset(year, dow, doy), + weekOffsetNext = firstWeekOffset(year + 1, dow, doy); + return (daysInYear(year) - weekOffset + weekOffsetNext) / 7; +}
@@ -0,0 +1,107 @@
+import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addUnitPriority } from './priorities'; +import { addRegexToken, match1to2, match1to4, match1to6, match2, match4, match6, matchSigned } from '../parse/regex'; +import { addWeekParseToken } from '../parse/token'; +import { weekOfYear, weeksInYear, dayOfYearFromWeeks } from './week-calendar-utils'; +import toInt from '../utils/to-int'; +import { hooks } from '../utils/hooks'; +import { createLocal } from '../create/local'; +import { createUTCDate } from '../create/date-from-array'; + +// FORMATTING + +addFormatToken(0, ['gg', 2], 0, function () { + return this.weekYear() % 100; +}); + +addFormatToken(0, ['GG', 2], 0, function () { + return this.isoWeekYear() % 100; +}); + +function addWeekYearFormatToken (token, getter) { + addFormatToken(0, [token, token.length], 0, getter); +} + +addWeekYearFormatToken('gggg', 'weekYear'); +addWeekYearFormatToken('ggggg', 'weekYear'); +addWeekYearFormatToken('GGGG', 'isoWeekYear'); +addWeekYearFormatToken('GGGGG', 'isoWeekYear'); + +// ALIASES + +addUnitAlias('weekYear', 'gg'); +addUnitAlias('isoWeekYear', 'GG'); + +// PRIORITY + +addUnitPriority('weekYear', 1); +addUnitPriority('isoWeekYear', 1); + + +// PARSING + +addRegexToken('G', matchSigned); +addRegexToken('g', matchSigned); +addRegexToken('GG', match1to2, match2); +addRegexToken('gg', match1to2, match2); +addRegexToken('GGGG', match1to4, match4); +addRegexToken('gggg', match1to4, match4); +addRegexToken('GGGGG', match1to6, match6); +addRegexToken('ggggg', match1to6, match6); + +addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) { + week[token.substr(0, 2)] = toInt(input); +}); + +addWeekParseToken(['gg', 'GG'], function (input, week, config, token) { + week[token] = hooks.parseTwoDigitYear(input); +}); + +// MOMENTS + +export function getSetWeekYear (input) { + return getSetWeekYearHelper.call(this, + input, + this.week(), + this.weekday(), + this.localeData()._week.dow, + this.localeData()._week.doy); +} + +export function getSetISOWeekYear (input) { + return getSetWeekYearHelper.call(this, + input, this.isoWeek(), this.isoWeekday(), 1, 4); +} + +export function getISOWeeksInYear () { + return weeksInYear(this.year(), 1, 4); +} + +export function getWeeksInYear () { + var weekInfo = this.localeData()._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); +} + +function getSetWeekYearHelper(input, week, weekday, dow, doy) { + var weeksTarget; + if (input == null) { + return weekOfYear(this, dow, doy).year; + } else { + weeksTarget = weeksInYear(input, dow, doy); + if (week > weeksTarget) { + week = weeksTarget; + } + return setWeekAll.call(this, input, week, weekday, dow, doy); + } +} + +function setWeekAll(weekYear, week, weekday, dow, doy) { + var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy), + date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear); + + this.year(date.getUTCFullYear()); + this.month(date.getUTCMonth()); + this.date(date.getUTCDate()); + return this; +}
@@ -0,0 +1,67 @@
+import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addUnitPriority } from './priorities'; +import { addRegexToken, match1to2, match2 } from '../parse/regex'; +import { addWeekParseToken } from '../parse/token'; +import toInt from '../utils/to-int'; +import { createLocal } from '../create/local'; +import { weekOfYear } from './week-calendar-utils'; + +// FORMATTING + +addFormatToken('w', ['ww', 2], 'wo', 'week'); +addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); + +// ALIASES + +addUnitAlias('week', 'w'); +addUnitAlias('isoWeek', 'W'); + +// PRIORITIES + +addUnitPriority('week', 5); +addUnitPriority('isoWeek', 5); + +// PARSING + +addRegexToken('w', match1to2); +addRegexToken('ww', match1to2, match2); +addRegexToken('W', match1to2); +addRegexToken('WW', match1to2, match2); + +addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) { + week[token.substr(0, 1)] = toInt(input); +}); + +// HELPERS + +// LOCALES + +export function localeWeek (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; +} + +export var defaultLocaleWeek = { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. +}; + +export function localeFirstDayOfWeek () { + return this._week.dow; +} + +export function localeFirstDayOfYear () { + return this._week.doy; +} + +// MOMENTS + +export function getSetWeek (input) { + var week = this.localeData().week(this); + return input == null ? week : this.add((input - week) * 7, 'd'); +} + +export function getSetISOWeek (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add((input - week) * 7, 'd'); +}
@@ -0,0 +1,75 @@
+import { makeGetSet } from '../moment/get-set'; +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addUnitPriority } from './priorities'; +import { addRegexToken, match1to2, match1to4, match1to6, match2, match4, match6, matchSigned } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { hooks } from '../utils/hooks'; +import { YEAR } from './constants'; +import toInt from '../utils/to-int'; + +// FORMATTING + +addFormatToken('Y', 0, 0, function () { + var y = this.year(); + return y <= 9999 ? '' + y : '+' + y; +}); + +addFormatToken(0, ['YY', 2], 0, function () { + return this.year() % 100; +}); + +addFormatToken(0, ['YYYY', 4], 0, 'year'); +addFormatToken(0, ['YYYYY', 5], 0, 'year'); +addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); + +// ALIASES + +addUnitAlias('year', 'y'); + +// PRIORITIES + +addUnitPriority('year', 1); + +// PARSING + +addRegexToken('Y', matchSigned); +addRegexToken('YY', match1to2, match2); +addRegexToken('YYYY', match1to4, match4); +addRegexToken('YYYYY', match1to6, match6); +addRegexToken('YYYYYY', match1to6, match6); + +addParseToken(['YYYYY', 'YYYYYY'], YEAR); +addParseToken('YYYY', function (input, array) { + array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input); +}); +addParseToken('YY', function (input, array) { + array[YEAR] = hooks.parseTwoDigitYear(input); +}); +addParseToken('Y', function (input, array) { + array[YEAR] = parseInt(input, 10); +}); + +// HELPERS + +export function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; +} + +function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; +} + +// HOOKS + +hooks.parseTwoDigitYear = function (input) { + return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); +}; + +// MOMENTS + +export var getSetYear = makeGetSet('FullYear', true); + +export function getIsLeapYear () { + return isLeapYear(this.year()); +}
@@ -0,0 +1,7 @@
+export default function absCeil (number) { + if (number < 0) { + return Math.floor(number); + } else { + return Math.ceil(number); + } +}
@@ -0,0 +1,8 @@
+export default function absFloor (number) { + if (number < 0) { + // -0 -> 0 + return Math.ceil(number) || 0; + } else { + return Math.floor(number); + } +}
@@ -0,0 +1,7 @@
+export default function absRound (number) { + if (number < 0) { + return Math.round(-1 * number) * -1; + } else { + return Math.round(number); + } +}
@@ -0,0 +1,16 @@
+import toInt from './to-int'; + +// compare two arrays, return the number of differences +export default function compareArrays(array1, array2, dontConvert) { + var len = Math.min(array1.length, array2.length), + lengthDiff = Math.abs(array1.length - array2.length), + diffs = 0, + i; + for (i = 0; i < len; i++) { + if ((dontConvert && array1[i] !== array2[i]) || + (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { + diffs++; + } + } + return diffs + lengthDiff; +}
@@ -0,0 +1,10 @@
+// Pick the first defined of two or three arguments. +export default function defaults(a, b, c) { + if (a != null) { + return a; + } + if (b != null) { + return b; + } + return c; +}
@@ -0,0 +1,40 @@
+import extend from './extend'; +import { hooks } from './hooks'; +import isUndefined from './is-undefined'; + +function warn(msg) { + if (hooks.suppressDeprecationWarnings === false && + (typeof console !== 'undefined') && console.warn) { + console.warn('Deprecation warning: ' + msg); + } +} + +export function deprecate(msg, fn) { + var firstTime = true; + + return extend(function () { + if (hooks.deprecationHandler != null) { + hooks.deprecationHandler(null, msg); + } + if (firstTime) { + warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack); + firstTime = false; + } + return fn.apply(this, arguments); + }, fn); +} + +var deprecations = {}; + +export function deprecateSimple(name, msg) { + if (hooks.deprecationHandler != null) { + hooks.deprecationHandler(name, msg); + } + if (!deprecations[name]) { + warn(msg); + deprecations[name] = true; + } +} + +hooks.suppressDeprecationWarnings = false; +hooks.deprecationHandler = null;
@@ -0,0 +1,19 @@
+import hasOwnProp from './has-own-prop'; + +export default function extend(a, b) { + for (var i in b) { + if (hasOwnProp(b, i)) { + a[i] = b[i]; + } + } + + if (hasOwnProp(b, 'toString')) { + a.toString = b.toString; + } + + if (hasOwnProp(b, 'valueOf')) { + a.valueOf = b.valueOf; + } + + return a; +}
@@ -0,0 +1,3 @@
+export default function hasOwnProp(a, b) { + return Object.prototype.hasOwnProperty.call(a, b); +}
@@ -0,0 +1,13 @@
+export { hooks, setHookCallback }; + +var hookCallback; + +function hooks () { + return hookCallback.apply(null, arguments); +} + +// This is done to register the method called with moment() +// without creating circular dependencies. +function setHookCallback (callback) { + hookCallback = callback; +}
@@ -0,0 +1,18 @@
+var indexOf; + +if (Array.prototype.indexOf) { + indexOf = Array.prototype.indexOf; +} else { + indexOf = function (o) { + // I know + var i; + for (i = 0; i < this.length; ++i) { + if (this[i] === o) { + return i; + } + } + return -1; + }; +} + +export { indexOf as default };
@@ -0,0 +1,3 @@
+export default function isArray(input) { + return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]'; +}
@@ -0,0 +1,3 @@
+export default function isDate(input) { + return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]'; +}
@@ -0,0 +1,3 @@
+export default function isFunction(input) { + return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]'; +}
@@ -0,0 +1,8 @@
+export default function isObjectEmpty(obj) { + var k; + for (k in obj) { + // even if its not own property I'd still call it non-empty + return false; + } + return true; +}
@@ -0,0 +1,3 @@
+export default function isObject(input) { + return Object.prototype.toString.call(input) === '[object Object]'; +}
@@ -0,0 +1,3 @@
+export default function isUndefined(input) { + return input === void 0; +}
@@ -0,0 +1,19 @@
+import hasOwnProp from './has-own-prop'; + +var keys; + +if (Object.keys) { + keys = Object.keys; +} else { + keys = function (obj) { + var i, res = []; + for (i in obj) { + if (hasOwnProp(obj, i)) { + res.push(i); + } + } + return res; + }; +} + +export { keys as default };
@@ -0,0 +1,7 @@
+export default function map(arr, fn) { + var res = [], i; + for (i = 0; i < arr.length; ++i) { + res.push(fn(arr[i], i)); + } + return res; +}
@@ -0,0 +1,19 @@
+var some; +if (Array.prototype.some) { + some = Array.prototype.some; +} else { + some = function (fun) { + var t = Object(this); + var len = t.length >>> 0; + + for (var i = 0; i < len; i++) { + if (i in t && fun.call(this, t[i], i, t)) { + return true; + } + } + + return false; + }; +} + +export { some as default };
@@ -0,0 +1,12 @@
+import absFloor from './abs-floor'; + +export default function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; + + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + value = absFloor(coercedNumber); + } + + return value; +}
@@ -0,0 +1,7 @@
+export default function zeroFill(number, targetLength, forceSign) { + var absNumber = '' + Math.abs(number), + zerosToFill = targetLength - absNumber.length, + sign = number >= 0; + return (sign ? (forceSign ? '+' : '') : '-') + + Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber; +}
@@ -0,0 +1,63 @@
+//! moment.js locale configuration +//! locale : Afrikaans [af] +//! author : Werner Mollentze : https://github.com/wernerm + +import moment from '../moment'; + +export default moment.defineLocale('af', { + months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'), + weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'), + weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'), + meridiemParse: /vm|nm/i, + isPM : function (input) { + return /^nm$/i.test(input); + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower ? 'vm' : 'VM'; + } else { + return isLower ? 'nm' : 'NM'; + } + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Vandag om] LT', + nextDay : '[Môre om] LT', + nextWeek : 'dddd [om] LT', + lastDay : '[Gister om] LT', + lastWeek : '[Laas] dddd [om] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'oor %s', + past : '%s gelede', + s : '\'n paar sekondes', + m : '\'n minuut', + mm : '%d minute', + h : '\'n uur', + hh : '%d ure', + d : '\'n dag', + dd : '%d dae', + M : '\'n maand', + MM : '%d maande', + y : '\'n jaar', + yy : '%d jaar' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter + }, + week : { + dow : 1, // Maandag is die eerste dag van die week. + doy : 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar. + } +});
@@ -0,0 +1,51 @@
+//! moment.js locale configuration +//! locale : Arabic (Morocco) [ar-ma] +//! author : ElFadili Yassine : https://github.com/ElFadiliY +//! author : Abdel Said : https://github.com/abdelsaid + +import moment from '../moment'; + +export default moment.defineLocale('ar-ma', { + months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[اليوم على الساعة] LT', + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'في %s', + past : 'منذ %s', + s : 'ثوان', + m : 'دقيقة', + mm : '%d دقائق', + h : 'ساعة', + hh : '%d ساعات', + d : 'يوم', + dd : '%d أيام', + M : 'شهر', + MM : '%d أشهر', + y : 'سنة', + yy : '%d سنوات' + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,95 @@
+//! moment.js locale configuration +//! locale : Arabic (Saudi Arabia) [ar-sa] +//! author : Suhail Alkowaileet : https://github.com/xsoh + +import moment from '../moment'; + +var symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' +}, numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' +}; + +export default moment.defineLocale('ar-sa', { + months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ص'; + } else { + return 'م'; + } + }, + calendar : { + sameDay: '[اليوم على الساعة] LT', + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'في %s', + past : 'منذ %s', + s : 'ثوان', + m : 'دقيقة', + mm : '%d دقائق', + h : 'ساعة', + hh : '%d ساعات', + d : 'يوم', + dd : '%d أيام', + M : 'شهر', + MM : '%d أشهر', + y : 'سنة', + yy : '%d سنوات' + }, + preparse: function (string) { + return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) { + return numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }).replace(/,/g, '،'); + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,49 @@
+//! moment.js locale configuration +//! locale : Arabic (Tunisia) [ar-tn] + +import moment from '../moment'; + +export default moment.defineLocale('ar-tn', { + months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[اليوم على الساعة] LT', + nextDay: '[غدا على الساعة] LT', + nextWeek: 'dddd [على الساعة] LT', + lastDay: '[أمس على الساعة] LT', + lastWeek: 'dddd [على الساعة] LT', + sameElse: 'L' + }, + relativeTime: { + future: 'في %s', + past: 'منذ %s', + s: 'ثوان', + m: 'دقيقة', + mm: '%d دقائق', + h: 'ساعة', + hh: '%d ساعات', + d: 'يوم', + dd: '%d أيام', + M: 'شهر', + MM: '%d أشهر', + y: 'سنة', + yy: '%d سنوات' + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,128 @@
+//! moment.js locale configuration +//! locale : Arabic [ar] +//! author : Abdel Said: https://github.com/abdelsaid +//! changes in months, weekdays: Ahmed Elkhatib +//! Native plural forms: forabi https://github.com/forabi + +import moment from '../moment'; + +var symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' +}, numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' +}, pluralForm = function (n) { + return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5; +}, plurals = { + s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'], + m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'], + h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'], + d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'], + M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'], + y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام'] +}, pluralize = function (u) { + return function (number, withoutSuffix, string, isFuture) { + var f = pluralForm(number), + str = plurals[u][pluralForm(number)]; + if (f === 2) { + str = str[withoutSuffix ? 0 : 1]; + } + return str.replace(/%d/i, number); + }; +}, months = [ + 'كانون الثاني يناير', + 'شباط فبراير', + 'آذار مارس', + 'نيسان أبريل', + 'أيار مايو', + 'حزيران يونيو', + 'تموز يوليو', + 'آب أغسطس', + 'أيلول سبتمبر', + 'تشرين الأول أكتوبر', + 'تشرين الثاني نوفمبر', + 'كانون الأول ديسمبر' +]; + +export default moment.defineLocale('ar', { + months : months, + monthsShort : months, + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'D/\u200FM/\u200FYYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ص'; + } else { + return 'م'; + } + }, + calendar : { + sameDay: '[اليوم عند الساعة] LT', + nextDay: '[غدًا عند الساعة] LT', + nextWeek: 'dddd [عند الساعة] LT', + lastDay: '[أمس عند الساعة] LT', + lastWeek: 'dddd [عند الساعة] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'بعد %s', + past : 'منذ %s', + s : pluralize('s'), + m : pluralize('m'), + mm : pluralize('m'), + h : pluralize('h'), + hh : pluralize('h'), + d : pluralize('d'), + dd : pluralize('d'), + M : pluralize('M'), + MM : pluralize('M'), + y : pluralize('y'), + yy : pluralize('y') + }, + preparse: function (string) { + return string.replace(/\u200f/g, '').replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) { + return numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }).replace(/,/g, '،'); + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,96 @@
+//! moment.js locale configuration +//! locale : Azerbaijani [az] +//! author : topchiyev : https://github.com/topchiyev + +import moment from '../moment'; + +var suffixes = { + 1: '-inci', + 5: '-inci', + 8: '-inci', + 70: '-inci', + 80: '-inci', + 2: '-nci', + 7: '-nci', + 20: '-nci', + 50: '-nci', + 3: '-üncü', + 4: '-üncü', + 100: '-üncü', + 6: '-ncı', + 9: '-uncu', + 10: '-uncu', + 30: '-uncu', + 60: '-ıncı', + 90: '-ıncı' +}; + +export default moment.defineLocale('az', { + months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'), + monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'), + weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'), + weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'), + weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[bugün saat] LT', + nextDay : '[sabah saat] LT', + nextWeek : '[gələn həftə] dddd [saat] LT', + lastDay : '[dünən] LT', + lastWeek : '[keçən həftə] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s sonra', + past : '%s əvvəl', + s : 'birneçə saniyyə', + m : 'bir dəqiqə', + mm : '%d dəqiqə', + h : 'bir saat', + hh : '%d saat', + d : 'bir gün', + dd : '%d gün', + M : 'bir ay', + MM : '%d ay', + y : 'bir il', + yy : '%d il' + }, + meridiemParse: /gecə|səhər|gündüz|axşam/, + isPM : function (input) { + return /^(gündüz|axşam)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'gecə'; + } else if (hour < 12) { + return 'səhər'; + } else if (hour < 17) { + return 'gündüz'; + } else { + return 'axşam'; + } + }, + ordinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/, + ordinal : function (number) { + if (number === 0) { // special case for zero + return number + '-ıncı'; + } + var a = number % 10, + b = number % 100 - a, + c = number >= 100 ? 100 : null; + return number + (suffixes[a] || suffixes[b] || suffixes[c]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,125 @@
+//! moment.js locale configuration +//! locale : Belarusian [be] +//! author : Dmitry Demidov : https://github.com/demidov91 +//! author: Praleska: http://praleska.pro/ +//! Author : Menelion Elensúle : https://github.com/Oire + +import moment from '../moment'; + +function plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); +} +function relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін', + 'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін', + 'dd': 'дзень_дні_дзён', + 'MM': 'месяц_месяцы_месяцаў', + 'yy': 'год_гады_гадоў' + }; + if (key === 'm') { + return withoutSuffix ? 'хвіліна' : 'хвіліну'; + } + else if (key === 'h') { + return withoutSuffix ? 'гадзіна' : 'гадзіну'; + } + else { + return number + ' ' + plural(format[key], +number); + } +} + +export default moment.defineLocale('be', { + months : { + format: 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_'), + standalone: 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_') + }, + monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'), + weekdays : { + format: 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_'), + standalone: 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'), + isFormat: /\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/ + }, + weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY г.', + LLL : 'D MMMM YYYY г., HH:mm', + LLLL : 'dddd, D MMMM YYYY г., HH:mm' + }, + calendar : { + sameDay: '[Сёння ў] LT', + nextDay: '[Заўтра ў] LT', + lastDay: '[Учора ў] LT', + nextWeek: function () { + return '[У] dddd [ў] LT'; + }, + lastWeek: function () { + switch (this.day()) { + case 0: + case 3: + case 5: + case 6: + return '[У мінулую] dddd [ў] LT'; + case 1: + case 2: + case 4: + return '[У мінулы] dddd [ў] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'праз %s', + past : '%s таму', + s : 'некалькі секунд', + m : relativeTimeWithPlural, + mm : relativeTimeWithPlural, + h : relativeTimeWithPlural, + hh : relativeTimeWithPlural, + d : 'дзень', + dd : relativeTimeWithPlural, + M : 'месяц', + MM : relativeTimeWithPlural, + y : 'год', + yy : relativeTimeWithPlural + }, + meridiemParse: /ночы|раніцы|дня|вечара/, + isPM : function (input) { + return /^(дня|вечара)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночы'; + } else if (hour < 12) { + return 'раніцы'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечара'; + } + }, + ordinalParse: /\d{1,2}-(і|ы|га)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + case 'w': + case 'W': + return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : number + '-ы'; + case 'D': + return number + '-га'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,81 @@
+//! moment.js locale configuration +//! locale : Bulgarian [bg] +//! author : Krasen Borisov : https://github.com/kraz + +import moment from '../moment'; + +export default moment.defineLocale('bg', { + months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'), + weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'D.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd, D MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[Днес в] LT', + nextDay : '[Утре в] LT', + nextWeek : 'dddd [в] LT', + lastDay : '[Вчера в] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + case 6: + return '[В изминалата] dddd [в] LT'; + case 1: + case 2: + case 4: + case 5: + return '[В изминалия] dddd [в] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'след %s', + past : 'преди %s', + s : 'няколко секунди', + m : 'минута', + mm : '%d минути', + h : 'час', + hh : '%d часа', + d : 'ден', + dd : '%d дни', + M : 'месец', + MM : '%d месеца', + y : 'година', + yy : '%d години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + ordinal : function (number) { + var lastDigit = number % 10, + last2Digits = number % 100; + if (number === 0) { + return number + '-ев'; + } else if (last2Digits === 0) { + return number + '-ен'; + } else if (last2Digits > 10 && last2Digits < 20) { + return number + '-ти'; + } else if (lastDigit === 1) { + return number + '-ви'; + } else if (lastDigit === 2) { + return number + '-ри'; + } else if (lastDigit === 7 || lastDigit === 8) { + return number + '-ми'; + } else { + return number + '-ти'; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,110 @@
+//! moment.js locale configuration +//! locale : Bengali [bn] +//! author : Kaushik Gandhi : https://github.com/kaushikgandhi + +import moment from '../moment'; + +var symbolMap = { + '1': '১', + '2': '২', + '3': '৩', + '4': '৪', + '5': '৫', + '6': '৬', + '7': '৭', + '8': '৮', + '9': '৯', + '0': '০' +}, +numberMap = { + '১': '1', + '২': '2', + '৩': '3', + '৪': '4', + '৫': '5', + '৬': '6', + '৭': '7', + '৮': '8', + '৯': '9', + '০': '0' +}; + +export default moment.defineLocale('bn', { + months : 'জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'), + monthsShort : 'জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্'.split('_'), + weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রবার_শনিবার'.split('_'), + weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্র_শনি'.split('_'), + weekdaysMin : 'রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি'.split('_'), + longDateFormat : { + LT : 'A h:mm সময়', + LTS : 'A h:mm:ss সময়', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm সময়', + LLLL : 'dddd, D MMMM YYYY, A h:mm সময়' + }, + calendar : { + sameDay : '[আজ] LT', + nextDay : '[আগামীকাল] LT', + nextWeek : 'dddd, LT', + lastDay : '[গতকাল] LT', + lastWeek : '[গত] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s পরে', + past : '%s আগে', + s : 'কয়েক সেকেন্ড', + m : 'এক মিনিট', + mm : '%d মিনিট', + h : 'এক ঘন্টা', + hh : '%d ঘন্টা', + d : 'এক দিন', + dd : '%d দিন', + M : 'এক মাস', + MM : '%d মাস', + y : 'এক বছর', + yy : '%d বছর' + }, + preparse: function (string) { + return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + meridiemParse: /রাত|সকাল|দুপুর|বিকাল|রাত/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if ((meridiem === 'রাত' && hour >= 4) || + (meridiem === 'দুপুর' && hour < 5) || + meridiem === 'বিকাল') { + return hour + 12; + } else { + return hour; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'রাত'; + } else if (hour < 10) { + return 'সকাল'; + } else if (hour < 17) { + return 'দুপুর'; + } else if (hour < 20) { + return 'বিকাল'; + } else { + return 'রাত'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,110 @@
+//! moment.js locale configuration +//! locale : Tibetan [bo] +//! author : Thupten N. Chakrishar : https://github.com/vajradog + +import moment from '../moment'; + +var symbolMap = { + '1': '༡', + '2': '༢', + '3': '༣', + '4': '༤', + '5': '༥', + '6': '༦', + '7': '༧', + '8': '༨', + '9': '༩', + '0': '༠' +}, +numberMap = { + '༡': '1', + '༢': '2', + '༣': '3', + '༤': '4', + '༥': '5', + '༦': '6', + '༧': '7', + '༨': '8', + '༩': '9', + '༠': '0' +}; + +export default moment.defineLocale('bo', { + months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'), + weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + longDateFormat : { + LT : 'A h:mm', + LTS : 'A h:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm', + LLLL : 'dddd, D MMMM YYYY, A h:mm' + }, + calendar : { + sameDay : '[དི་རིང] LT', + nextDay : '[སང་ཉིན] LT', + nextWeek : '[བདུན་ཕྲག་རྗེས་མ], LT', + lastDay : '[ཁ་སང] LT', + lastWeek : '[བདུན་ཕྲག་མཐའ་མ] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ལ་', + past : '%s སྔན་ལ', + s : 'ལམ་སང', + m : 'སྐར་མ་གཅིག', + mm : '%d སྐར་མ', + h : 'ཆུ་ཚོད་གཅིག', + hh : '%d ཆུ་ཚོད', + d : 'ཉིན་གཅིག', + dd : '%d ཉིན་', + M : 'ཟླ་བ་གཅིག', + MM : '%d ཟླ་བ', + y : 'ལོ་གཅིག', + yy : '%d ལོ' + }, + preparse: function (string) { + return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if ((meridiem === 'མཚན་མོ' && hour >= 4) || + (meridiem === 'ཉིན་གུང' && hour < 5) || + meridiem === 'དགོང་དག') { + return hour + 12; + } else { + return hour; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'མཚན་མོ'; + } else if (hour < 10) { + return 'ཞོགས་ཀས'; + } else if (hour < 17) { + return 'ཉིན་གུང'; + } else if (hour < 20) { + return 'དགོང་དག'; + } else { + return 'མཚན་མོ'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,99 @@
+//! moment.js locale configuration +//! locale : Breton [br] +//! author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou + +import moment from '../moment'; + +function relativeTimeWithMutation(number, withoutSuffix, key) { + var format = { + 'mm': 'munutenn', + 'MM': 'miz', + 'dd': 'devezh' + }; + return number + ' ' + mutation(format[key], number); +} +function specialMutationForYears(number) { + switch (lastNumber(number)) { + case 1: + case 3: + case 4: + case 5: + case 9: + return number + ' bloaz'; + default: + return number + ' vloaz'; + } +} +function lastNumber(number) { + if (number > 9) { + return lastNumber(number % 10); + } + return number; +} +function mutation(text, number) { + if (number === 2) { + return softMutation(text); + } + return text; +} +function softMutation(text) { + var mutationTable = { + 'm': 'v', + 'b': 'v', + 'd': 'z' + }; + if (mutationTable[text.charAt(0)] === undefined) { + return text; + } + return mutationTable[text.charAt(0)] + text.substring(1); +} + +export default moment.defineLocale('br', { + months : 'Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split('_'), + monthsShort : 'Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'), + weekdays : 'Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn'.split('_'), + weekdaysShort : 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'), + weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'h[e]mm A', + LTS : 'h[e]mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D [a viz] MMMM YYYY', + LLL : 'D [a viz] MMMM YYYY h[e]mm A', + LLLL : 'dddd, D [a viz] MMMM YYYY h[e]mm A' + }, + calendar : { + sameDay : '[Hiziv da] LT', + nextDay : '[Warc\'hoazh da] LT', + nextWeek : 'dddd [da] LT', + lastDay : '[Dec\'h da] LT', + lastWeek : 'dddd [paset da] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'a-benn %s', + past : '%s \'zo', + s : 'un nebeud segondennoù', + m : 'ur vunutenn', + mm : relativeTimeWithMutation, + h : 'un eur', + hh : '%d eur', + d : 'un devezh', + dd : relativeTimeWithMutation, + M : 'ur miz', + MM : relativeTimeWithMutation, + y : 'ur bloaz', + yy : specialMutationForYears + }, + ordinalParse: /\d{1,2}(añ|vet)/, + ordinal : function (number) { + var output = (number === 1) ? 'añ' : 'vet'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,134 @@
+//! moment.js locale configuration +//! locale : Bosnian [bs] +//! author : Nedim Cholich : https://github.com/frontyard +//! based on (hr) translation by Bojan Marković + +import moment from '../moment'; + +function translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } +} + +export default moment.defineLocale('bs', { + months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : translate, + mm : translate, + h : translate, + hh : translate, + d : 'dan', + dd : translate, + M : 'mjesec', + MM : translate, + y : 'godinu', + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,72 @@
+//! moment.js locale configuration +//! locale : Catalan [ca] +//! author : Juan G. Hurtado : https://github.com/juanghurtado + +import moment from '../moment'; + +export default moment.defineLocale('ca', { + months : 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'), + monthsShort : 'gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.'.split('_'), + monthsParseExact : true, + weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'), + weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'), + weekdaysMin : 'Dg_Dl_Dt_Dc_Dj_Dv_Ds'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd D MMMM YYYY H:mm' + }, + calendar : { + sameDay : function () { + return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + nextDay : function () { + return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + lastDay : function () { + return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'en %s', + past : 'fa %s', + s : 'uns segons', + m : 'un minut', + mm : '%d minuts', + h : 'una hora', + hh : '%d hores', + d : 'un dia', + dd : '%d dies', + M : 'un mes', + MM : '%d mesos', + y : 'un any', + yy : '%d anys' + }, + ordinalParse: /\d{1,2}(r|n|t|è|a)/, + ordinal : function (number, period) { + var output = (number === 1) ? 'r' : + (number === 2) ? 'n' : + (number === 3) ? 'r' : + (number === 4) ? 't' : 'è'; + if (period === 'w' || period === 'W') { + output = 'a'; + } + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,163 @@
+//! moment.js locale configuration +//! locale : Czech [cs] +//! author : petrbela : https://github.com/petrbela + +import moment from '../moment'; + +var months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_'), + monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_'); +function plural(n) { + return (n > 1) && (n < 5) && (~~(n / 10) !== 1); +} +function translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': // a few seconds / in a few seconds / a few seconds ago + return (withoutSuffix || isFuture) ? 'pár sekund' : 'pár sekundami'; + case 'm': // a minute / in a minute / a minute ago + return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou'); + case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'minuty' : 'minut'); + } else { + return result + 'minutami'; + } + break; + case 'h': // an hour / in an hour / an hour ago + return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou'); + case 'hh': // 9 hours / in 9 hours / 9 hours ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'hodiny' : 'hodin'); + } else { + return result + 'hodinami'; + } + break; + case 'd': // a day / in a day / a day ago + return (withoutSuffix || isFuture) ? 'den' : 'dnem'; + case 'dd': // 9 days / in 9 days / 9 days ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'dny' : 'dní'); + } else { + return result + 'dny'; + } + break; + case 'M': // a month / in a month / a month ago + return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem'; + case 'MM': // 9 months / in 9 months / 9 months ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'měsíce' : 'měsíců'); + } else { + return result + 'měsíci'; + } + break; + case 'y': // a year / in a year / a year ago + return (withoutSuffix || isFuture) ? 'rok' : 'rokem'; + case 'yy': // 9 years / in 9 years / 9 years ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'roky' : 'let'); + } else { + return result + 'lety'; + } + break; + } +} + +export default moment.defineLocale('cs', { + months : months, + monthsShort : monthsShort, + monthsParse : (function (months, monthsShort) { + var i, _monthsParse = []; + for (i = 0; i < 12; i++) { + // use custom parser to solve problem with July (červenec) + _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i'); + } + return _monthsParse; + }(months, monthsShort)), + shortMonthsParse : (function (monthsShort) { + var i, _shortMonthsParse = []; + for (i = 0; i < 12; i++) { + _shortMonthsParse[i] = new RegExp('^' + monthsShort[i] + '$', 'i'); + } + return _shortMonthsParse; + }(monthsShort)), + longMonthsParse : (function (months) { + var i, _longMonthsParse = []; + for (i = 0; i < 12; i++) { + _longMonthsParse[i] = new RegExp('^' + months[i] + '$', 'i'); + } + return _longMonthsParse; + }(months)), + weekdays : 'neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota'.split('_'), + weekdaysShort : 'ne_po_út_st_čt_pá_so'.split('_'), + weekdaysMin : 'ne_po_út_st_čt_pá_so'.split('_'), + longDateFormat : { + LT: 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd D. MMMM YYYY H:mm', + l : 'D. M. YYYY' + }, + calendar : { + sameDay: '[dnes v] LT', + nextDay: '[zítra v] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[v neděli v] LT'; + case 1: + case 2: + return '[v] dddd [v] LT'; + case 3: + return '[ve středu v] LT'; + case 4: + return '[ve čtvrtek v] LT'; + case 5: + return '[v pátek v] LT'; + case 6: + return '[v sobotu v] LT'; + } + }, + lastDay: '[včera v] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[minulou neděli v] LT'; + case 1: + case 2: + return '[minulé] dddd [v] LT'; + case 3: + return '[minulou středu v] LT'; + case 4: + case 5: + return '[minulý] dddd [v] LT'; + case 6: + return '[minulou sobotu v] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'za %s', + past : 'před %s', + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinalParse : /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,53 @@
+//! moment.js locale configuration +//! locale : Chuvash [cv] +//! author : Anatoly Mironov : https://github.com/mirontoli + +import moment from '../moment'; + +export default moment.defineLocale('cv', { + months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'), + monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'), + weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'), + weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'), + weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]', + LLL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm', + LLLL : 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm' + }, + calendar : { + sameDay: '[Паян] LT [сехетре]', + nextDay: '[Ыран] LT [сехетре]', + lastDay: '[Ӗнер] LT [сехетре]', + nextWeek: '[Ҫитес] dddd LT [сехетре]', + lastWeek: '[Иртнӗ] dddd LT [сехетре]', + sameElse: 'L' + }, + relativeTime : { + future : function (output) { + var affix = /сехет$/i.exec(output) ? 'рен' : /ҫул$/i.exec(output) ? 'тан' : 'ран'; + return output + affix; + }, + past : '%s каялла', + s : 'пӗр-ик ҫеккунт', + m : 'пӗр минут', + mm : '%d минут', + h : 'пӗр сехет', + hh : '%d сехет', + d : 'пӗр кун', + dd : '%d кун', + M : 'пӗр уйӑх', + MM : '%d уйӑх', + y : 'пӗр ҫул', + yy : '%d ҫул' + }, + ordinalParse: /\d{1,2}-мӗш/, + ordinal : '%d-мӗш', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +});
@@ -0,0 +1,71 @@
+//! moment.js locale configuration +//! locale : Welsh [cy] +//! author : Robert Allen + +import moment from '../moment'; + +export default moment.defineLocale('cy', { + months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'), + monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'), + weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'), + weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'), + weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'), + weekdaysParseExact : true, + // time formats are the same as en-gb + longDateFormat: { + LT: 'HH:mm', + LTS : 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd, D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[Heddiw am] LT', + nextDay: '[Yfory am] LT', + nextWeek: 'dddd [am] LT', + lastDay: '[Ddoe am] LT', + lastWeek: 'dddd [diwethaf am] LT', + sameElse: 'L' + }, + relativeTime: { + future: 'mewn %s', + past: '%s yn ôl', + s: 'ychydig eiliadau', + m: 'munud', + mm: '%d munud', + h: 'awr', + hh: '%d awr', + d: 'diwrnod', + dd: '%d diwrnod', + M: 'mis', + MM: '%d mis', + y: 'blwyddyn', + yy: '%d flynedd' + }, + ordinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/, + // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh + ordinal: function (number) { + var b = number, + output = '', + lookup = [ + '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed + 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed + ]; + if (b > 20) { + if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) { + output = 'fed'; // not 30ain, 70ain or 90ain + } else { + output = 'ain'; + } + } else if (b > 0) { + output = lookup[b]; + } + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,51 @@
+//! moment.js locale configuration +//! locale : Danish [da] +//! author : Ulrik Nielsen : https://github.com/mrbase + +import moment from '../moment'; + +export default moment.defineLocale('da', { + months : 'januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december'.split('_'), + monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'), + weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'), + weekdaysShort : 'søn_man_tir_ons_tor_fre_lør'.split('_'), + weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY HH:mm', + LLLL : 'dddd [d.] D. MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[I dag kl.] LT', + nextDay : '[I morgen kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[I går kl.] LT', + lastWeek : '[sidste] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'om %s', + past : '%s siden', + s : 'få sekunder', + m : 'et minut', + mm : '%d minutter', + h : 'en time', + hh : '%d timer', + d : 'en dag', + dd : '%d dage', + M : 'en måned', + MM : '%d måneder', + y : 'et år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,69 @@
+//! moment.js locale configuration +//! locale : German (Austria) [de-at] +//! author : lluchs : https://github.com/lluchs +//! author: Menelion Elensúle: https://github.com/Oire +//! author : Martin Groller : https://github.com/MadMG +//! author : Mikolaj Dadela : https://github.com/mik01aj + +import moment from '../moment'; + +function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eine Minute', 'einer Minute'], + 'h': ['eine Stunde', 'einer Stunde'], + 'd': ['ein Tag', 'einem Tag'], + 'dd': [number + ' Tage', number + ' Tagen'], + 'M': ['ein Monat', 'einem Monat'], + 'MM': [number + ' Monate', number + ' Monaten'], + 'y': ['ein Jahr', 'einem Jahr'], + 'yy': [number + ' Jahre', number + ' Jahren'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; +} + +export default moment.defineLocale('de-at', { + months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort : 'Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + monthsParseExact : true, + weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'), + weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'), + weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY HH:mm', + LLLL : 'dddd, D. MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + relativeTime : { + future : 'in %s', + past : 'vor %s', + s : 'ein paar Sekunden', + m : processRelativeTime, + mm : '%d Minuten', + h : processRelativeTime, + hh : '%d Stunden', + d : processRelativeTime, + dd : processRelativeTime, + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +});
@@ -0,0 +1,68 @@
+//! moment.js locale configuration +//! locale : German [de] +//! author : lluchs : https://github.com/lluchs +//! author: Menelion Elensúle: https://github.com/Oire +//! author : Mikolaj Dadela : https://github.com/mik01aj + +import moment from '../moment'; + +function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eine Minute', 'einer Minute'], + 'h': ['eine Stunde', 'einer Stunde'], + 'd': ['ein Tag', 'einem Tag'], + 'dd': [number + ' Tage', number + ' Tagen'], + 'M': ['ein Monat', 'einem Monat'], + 'MM': [number + ' Monate', number + ' Monaten'], + 'y': ['ein Jahr', 'einem Jahr'], + 'yy': [number + ' Jahre', number + ' Jahren'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; +} + +export default moment.defineLocale('de', { + months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort : 'Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + monthsParseExact : true, + weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'), + weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'), + weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY HH:mm', + LLLL : 'dddd, D. MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + relativeTime : { + future : 'in %s', + past : 'vor %s', + s : 'ein paar Sekunden', + m : processRelativeTime, + mm : '%d Minuten', + h : processRelativeTime, + hh : '%d Stunden', + d : processRelativeTime, + dd : processRelativeTime, + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +});
@@ -0,0 +1,89 @@
+//! moment.js locale configuration +//! locale : Maldivian [dv] +//! author : Jawish Hameed : https://github.com/jawish + +import moment from '../moment'; + +var months = [ + 'ޖެނުއަރީ', + 'ފެބްރުއަރީ', + 'މާރިޗު', + 'އޭޕްރީލު', + 'މޭ', + 'ޖޫން', + 'ޖުލައި', + 'އޯގަސްޓު', + 'ސެޕްޓެމްބަރު', + 'އޮކްޓޯބަރު', + 'ނޮވެމްބަރު', + 'ޑިސެމްބަރު' +], weekdays = [ + 'އާދިއްތަ', + 'ހޯމަ', + 'އަންގާރަ', + 'ބުދަ', + 'ބުރާސްފަތި', + 'ހުކުރު', + 'ހޮނިހިރު' +]; + +export default moment.defineLocale('dv', { + months : months, + monthsShort : months, + weekdays : weekdays, + weekdaysShort : weekdays, + weekdaysMin : 'އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި'.split('_'), + longDateFormat : { + + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'D/M/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + meridiemParse: /މކ|މފ/, + isPM : function (input) { + return 'މފ' === input; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'މކ'; + } else { + return 'މފ'; + } + }, + calendar : { + sameDay : '[މިއަދު] LT', + nextDay : '[މާދަމާ] LT', + nextWeek : 'dddd LT', + lastDay : '[އިއްޔެ] LT', + lastWeek : '[ފާއިތުވި] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : 'ތެރޭގައި %s', + past : 'ކުރިން %s', + s : 'ސިކުންތުކޮޅެއް', + m : 'މިނިޓެއް', + mm : 'މިނިޓު %d', + h : 'ގަޑިއިރެއް', + hh : 'ގަޑިއިރު %d', + d : 'ދުވަހެއް', + dd : 'ދުވަސް %d', + M : 'މަހެއް', + MM : 'މަސް %d', + y : 'އަހަރެއް', + yy : 'އަހަރު %d' + }, + preparse: function (string) { + return string.replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/,/g, '،'); + }, + week : { + dow : 7, // Sunday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +});
@@ -0,0 +1,86 @@
+//! moment.js locale configuration +//! locale : Greek [el] +//! author : Aggelos Karalias : https://github.com/mehiel + +import moment from '../moment'; +import isFunction from '../lib/utils/is-function'; + +export default moment.defineLocale('el', { + monthsNominativeEl : 'Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος'.split('_'), + monthsGenitiveEl : 'Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου'.split('_'), + months : function (momentToFormat, format) { + if (/D/.test(format.substring(0, format.indexOf('MMMM')))) { // if there is a day number before 'MMMM' + return this._monthsGenitiveEl[momentToFormat.month()]; + } else { + return this._monthsNominativeEl[momentToFormat.month()]; + } + }, + monthsShort : 'Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ'.split('_'), + weekdays : 'Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο'.split('_'), + weekdaysShort : 'Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ'.split('_'), + weekdaysMin : 'Κυ_Δε_Τρ_Τε_Πε_Πα_Σα'.split('_'), + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'μμ' : 'ΜΜ'; + } else { + return isLower ? 'πμ' : 'ΠΜ'; + } + }, + isPM : function (input) { + return ((input + '').toLowerCase()[0] === 'μ'); + }, + meridiemParse : /[ΠΜ]\.?Μ?\.?/i, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendarEl : { + sameDay : '[Σήμερα {}] LT', + nextDay : '[Αύριο {}] LT', + nextWeek : 'dddd [{}] LT', + lastDay : '[Χθες {}] LT', + lastWeek : function () { + switch (this.day()) { + case 6: + return '[το προηγούμενο] dddd [{}] LT'; + default: + return '[την προηγούμενη] dddd [{}] LT'; + } + }, + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendarEl[key], + hours = mom && mom.hours(); + if (isFunction(output)) { + output = output.apply(mom); + } + return output.replace('{}', (hours % 12 === 1 ? 'στη' : 'στις')); + }, + relativeTime : { + future : 'σε %s', + past : '%s πριν', + s : 'λίγα δευτερόλεπτα', + m : 'ένα λεπτό', + mm : '%d λεπτά', + h : 'μία ώρα', + hh : '%d ώρες', + d : 'μία μέρα', + dd : '%d μέρες', + M : 'ένας μήνας', + MM : '%d μήνες', + y : 'ένας χρόνος', + yy : '%d χρόνια' + }, + ordinalParse: /\d{1,2}η/, + ordinal: '%dη', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4st is the first week of the year. + } +}); +
@@ -0,0 +1,57 @@
+//! moment.js locale configuration +//! locale : English (Australia) [en-au] + +import moment from '../moment'; + +export default moment.defineLocale('en-au', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,53 @@
+//! moment.js locale configuration +//! locale : English (Canada) [en-ca] +//! author : Jonathan Abourbih : https://github.com/jonbca + +import moment from '../moment'; + +export default moment.defineLocale('en-ca', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'YYYY-MM-DD', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY h:mm A', + LLLL : 'dddd, MMMM D, YYYY h:mm A' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } +});
@@ -0,0 +1,58 @@
+//! moment.js locale configuration +//! locale : English (United Kingdom) [en-gb] +//! author : Chris Gedrim : https://github.com/chrisgedrim + +import moment from '../moment'; + +export default moment.defineLocale('en-gb', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,58 @@
+//! moment.js locale configuration +//! locale : English (Ireland) [en-ie] +//! author : Chris Cartlidge : https://github.com/chriscartlidge + +import moment from '../moment'; + +export default moment.defineLocale('en-ie', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,56 @@
+//! moment.js locale configuration +//! locale : English (New Zealand) [en-nz] + +import moment from '../moment'; + +export default moment.defineLocale('en-nz', { + months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), + weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), + weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), + weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'in %s', + past : '%s ago', + s : 'a few seconds', + m : 'a minute', + mm : '%d minutes', + h : 'an hour', + hh : '%d hours', + d : 'a day', + dd : '%d days', + M : 'a month', + MM : '%d months', + y : 'a year', + yy : '%d years' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +});
@@ -0,0 +1,64 @@
+//! moment.js locale configuration +//! locale : Esperanto [eo] +//! author : Colin Dean : https://github.com/colindean +//! komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko. +//! Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni! + +import moment from '../moment'; + +export default moment.defineLocale('eo', { + months : 'januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro'.split('_'), + monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec'.split('_'), + weekdays : 'Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato'.split('_'), + weekdaysShort : 'Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Ĵa_Ve_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'D[-an de] MMMM, YYYY', + LLL : 'D[-an de] MMMM, YYYY HH:mm', + LLLL : 'dddd, [la] D[-an de] MMMM, YYYY HH:mm' + }, + meridiemParse: /[ap]\.t\.m/i, + isPM: function (input) { + return input.charAt(0).toLowerCase() === 'p'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'p.t.m.' : 'P.T.M.'; + } else { + return isLower ? 'a.t.m.' : 'A.T.M.'; + } + }, + calendar : { + sameDay : '[Hodiaŭ je] LT', + nextDay : '[Morgaŭ je] LT', + nextWeek : 'dddd [je] LT', + lastDay : '[Hieraŭ je] LT', + lastWeek : '[pasinta] dddd [je] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'je %s', + past : 'antaŭ %s', + s : 'sekundoj', + m : 'minuto', + mm : '%d minutoj', + h : 'horo', + hh : '%d horoj', + d : 'tago',//ne 'diurno', ĉar estas uzita por proksimumo + dd : '%d tagoj', + M : 'monato', + MM : '%d monatoj', + y : 'jaro', + yy : '%d jaroj' + }, + ordinalParse: /\d{1,2}a/, + ordinal : '%da', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,71 @@
+//! moment.js locale configuration +//! locale : Spanish (Dominican Republic) [es-do] + +import moment from '../moment'; + +var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_'), + monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_'); + +export default moment.defineLocale('es-do', { + months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShort[m.month()]; + } else { + return monthsShortDot[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'), + weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'), + weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY h:mm A', + LLLL : 'dddd, D [de] MMMM [de] YYYY h:mm A' + }, + calendar : { + sameDay : function () { + return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextDay : function () { + return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastDay : function () { + return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'en %s', + past : 'hace %s', + s : 'unos segundos', + m : 'un minuto', + mm : '%d minutos', + h : 'una hora', + hh : '%d horas', + d : 'un día', + dd : '%d días', + M : 'un mes', + MM : '%d meses', + y : 'un año', + yy : '%d años' + }, + ordinalParse : /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,72 @@
+//! moment.js locale configuration +//! locale : Spanish [es] +//! author : Julio Napurí : https://github.com/julionc + +import moment from '../moment'; + +var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_'), + monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_'); + +export default moment.defineLocale('es', { + months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShort[m.month()]; + } else { + return monthsShortDot[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'), + weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'), + weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY H:mm', + LLLL : 'dddd, D [de] MMMM [de] YYYY H:mm' + }, + calendar : { + sameDay : function () { + return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextDay : function () { + return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + nextWeek : function () { + return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastDay : function () { + return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + lastWeek : function () { + return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'en %s', + past : 'hace %s', + s : 'unos segundos', + m : 'un minuto', + mm : '%d minutos', + h : 'una hora', + hh : '%d horas', + d : 'un día', + dd : '%d días', + M : 'un mes', + MM : '%d meses', + y : 'un año', + yy : '%d años' + }, + ordinalParse : /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,71 @@
+//! moment.js locale configuration +//! locale : Estonian [et] +//! author : Henry Kehlmann : https://github.com/madhenry +//! improvements : Illimar Tambek : https://github.com/ragulka + +import moment from '../moment'; + +function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'], + 'm' : ['ühe minuti', 'üks minut'], + 'mm': [number + ' minuti', number + ' minutit'], + 'h' : ['ühe tunni', 'tund aega', 'üks tund'], + 'hh': [number + ' tunni', number + ' tundi'], + 'd' : ['ühe päeva', 'üks päev'], + 'M' : ['kuu aja', 'kuu aega', 'üks kuu'], + 'MM': [number + ' kuu', number + ' kuud'], + 'y' : ['ühe aasta', 'aasta', 'üks aasta'], + 'yy': [number + ' aasta', number + ' aastat'] + }; + if (withoutSuffix) { + return format[key][2] ? format[key][2] : format[key][1]; + } + return isFuture ? format[key][0] : format[key][1]; +} + +export default moment.defineLocale('et', { + months : 'jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember'.split('_'), + monthsShort : 'jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets'.split('_'), + weekdays : 'pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev'.split('_'), + weekdaysShort : 'P_E_T_K_N_R_L'.split('_'), + weekdaysMin : 'P_E_T_K_N_R_L'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[Täna,] LT', + nextDay : '[Homme,] LT', + nextWeek : '[Järgmine] dddd LT', + lastDay : '[Eile,] LT', + lastWeek : '[Eelmine] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s pärast', + past : '%s tagasi', + s : processRelativeTime, + m : processRelativeTime, + mm : processRelativeTime, + h : processRelativeTime, + hh : processRelativeTime, + d : processRelativeTime, + dd : '%d päeva', + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,57 @@
+//! moment.js locale configuration +//! locale : Basque [eu] +//! author : Eneko Illarramendi : https://github.com/eillarra + +import moment from '../moment'; + +export default moment.defineLocale('eu', { + months : 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split('_'), + monthsShort : 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split('_'), + monthsParseExact : true, + weekdays : 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split('_'), + weekdaysShort : 'ig._al._ar._az._og._ol._lr.'.split('_'), + weekdaysMin : 'ig_al_ar_az_og_ol_lr'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'YYYY[ko] MMMM[ren] D[a]', + LLL : 'YYYY[ko] MMMM[ren] D[a] HH:mm', + LLLL : 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm', + l : 'YYYY-M-D', + ll : 'YYYY[ko] MMM D[a]', + lll : 'YYYY[ko] MMM D[a] HH:mm', + llll : 'ddd, YYYY[ko] MMM D[a] HH:mm' + }, + calendar : { + sameDay : '[gaur] LT[etan]', + nextDay : '[bihar] LT[etan]', + nextWeek : 'dddd LT[etan]', + lastDay : '[atzo] LT[etan]', + lastWeek : '[aurreko] dddd LT[etan]', + sameElse : 'L' + }, + relativeTime : { + future : '%s barru', + past : 'duela %s', + s : 'segundo batzuk', + m : 'minutu bat', + mm : '%d minutu', + h : 'ordu bat', + hh : '%d ordu', + d : 'egun bat', + dd : '%d egun', + M : 'hilabete bat', + MM : '%d hilabete', + y : 'urte bat', + yy : '%d urte' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,97 @@
+//! moment.js locale configuration +//! locale : Persian [fa] +//! author : Ebrahim Byagowi : https://github.com/ebraminio + +import moment from '../moment'; + +var symbolMap = { + '1': '۱', + '2': '۲', + '3': '۳', + '4': '۴', + '5': '۵', + '6': '۶', + '7': '۷', + '8': '۸', + '9': '۹', + '0': '۰' +}, numberMap = { + '۱': '1', + '۲': '2', + '۳': '3', + '۴': '4', + '۵': '5', + '۶': '6', + '۷': '7', + '۸': '8', + '۹': '9', + '۰': '0' +}; + +export default moment.defineLocale('fa', { + months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + meridiemParse: /قبل از ظهر|بعد از ظهر/, + isPM: function (input) { + return /بعد از ظهر/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'قبل از ظهر'; + } else { + return 'بعد از ظهر'; + } + }, + calendar : { + sameDay : '[امروز ساعت] LT', + nextDay : '[فردا ساعت] LT', + nextWeek : 'dddd [ساعت] LT', + lastDay : '[دیروز ساعت] LT', + lastWeek : 'dddd [پیش] [ساعت] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'در %s', + past : '%s پیش', + s : 'چندین ثانیه', + m : 'یک دقیقه', + mm : '%d دقیقه', + h : 'یک ساعت', + hh : '%d ساعت', + d : 'یک روز', + dd : '%d روز', + M : 'یک ماه', + MM : '%d ماه', + y : 'یک سال', + yy : '%d سال' + }, + preparse: function (string) { + return string.replace(/[۰-۹]/g, function (match) { + return numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }).replace(/,/g, '،'); + }, + ordinalParse: /\d{1,2}م/, + ordinal : '%dم', + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,98 @@
+//! moment.js locale configuration +//! locale : Finnish [fi] +//! author : Tarmo Aidantausta : https://github.com/bleadof + +import moment from '../moment'; + +var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '), + numbersFuture = [ + 'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden', + numbersPast[7], numbersPast[8], numbersPast[9] + ]; +function translate(number, withoutSuffix, key, isFuture) { + var result = ''; + switch (key) { + case 's': + return isFuture ? 'muutaman sekunnin' : 'muutama sekunti'; + case 'm': + return isFuture ? 'minuutin' : 'minuutti'; + case 'mm': + result = isFuture ? 'minuutin' : 'minuuttia'; + break; + case 'h': + return isFuture ? 'tunnin' : 'tunti'; + case 'hh': + result = isFuture ? 'tunnin' : 'tuntia'; + break; + case 'd': + return isFuture ? 'päivän' : 'päivä'; + case 'dd': + result = isFuture ? 'päivän' : 'päivää'; + break; + case 'M': + return isFuture ? 'kuukauden' : 'kuukausi'; + case 'MM': + result = isFuture ? 'kuukauden' : 'kuukautta'; + break; + case 'y': + return isFuture ? 'vuoden' : 'vuosi'; + case 'yy': + result = isFuture ? 'vuoden' : 'vuotta'; + break; + } + result = verbalNumber(number, isFuture) + ' ' + result; + return result; +} +function verbalNumber(number, isFuture) { + return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number; +} + +export default moment.defineLocale('fi', { + months : 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split('_'), + monthsShort : 'tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu'.split('_'), + weekdays : 'sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai'.split('_'), + weekdaysShort : 'su_ma_ti_ke_to_pe_la'.split('_'), + weekdaysMin : 'su_ma_ti_ke_to_pe_la'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD.MM.YYYY', + LL : 'Do MMMM[ta] YYYY', + LLL : 'Do MMMM[ta] YYYY, [klo] HH.mm', + LLLL : 'dddd, Do MMMM[ta] YYYY, [klo] HH.mm', + l : 'D.M.YYYY', + ll : 'Do MMM YYYY', + lll : 'Do MMM YYYY, [klo] HH.mm', + llll : 'ddd, Do MMM YYYY, [klo] HH.mm' + }, + calendar : { + sameDay : '[tänään] [klo] LT', + nextDay : '[huomenna] [klo] LT', + nextWeek : 'dddd [klo] LT', + lastDay : '[eilen] [klo] LT', + lastWeek : '[viime] dddd[na] [klo] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s päästä', + past : '%s sitten', + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,51 @@
+//! moment.js locale configuration +//! locale : Faroese [fo] +//! author : Ragnar Johannesen : https://github.com/ragnar123 + +import moment from '../moment'; + +export default moment.defineLocale('fo', { + months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), + weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'), + weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'), + weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D. MMMM, YYYY HH:mm' + }, + calendar : { + sameDay : '[Í dag kl.] LT', + nextDay : '[Í morgin kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[Í gjár kl.] LT', + lastWeek : '[síðstu] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'um %s', + past : '%s síðani', + s : 'fá sekund', + m : 'ein minutt', + mm : '%d minuttir', + h : 'ein tími', + hh : '%d tímar', + d : 'ein dagur', + dd : '%d dagar', + M : 'ein mánaði', + MM : '%d mánaðir', + y : 'eitt ár', + yy : '%d ár' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,51 @@
+//! moment.js locale configuration +//! locale : French (Canada) [fr-ca] +//! author : Jonathan Abourbih : https://github.com/jonbca + +import moment from '../moment'; + +export default moment.defineLocale('fr-ca', { + months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), + monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), + monthsParseExact : true, + weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), + weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Aujourd\'hui à] LT', + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dans %s', + past : 'il y a %s', + s : 'quelques secondes', + m : 'une minute', + mm : '%d minutes', + h : 'une heure', + hh : '%d heures', + d : 'un jour', + dd : '%d jours', + M : 'un mois', + MM : '%d mois', + y : 'un an', + yy : '%d ans' + }, + ordinalParse: /\d{1,2}(er|e)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : 'e'); + } +}); +
@@ -0,0 +1,55 @@
+//! moment.js locale configuration +//! locale : French (Switzerland) [fr-ch] +//! author : Gaspard Bucher : https://github.com/gaspard + +import moment from '../moment'; + +export default moment.defineLocale('fr-ch', { + months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), + monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), + monthsParseExact : true, + weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), + weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Aujourd\'hui à] LT', + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dans %s', + past : 'il y a %s', + s : 'quelques secondes', + m : 'une minute', + mm : '%d minutes', + h : 'une heure', + hh : '%d heures', + d : 'un jour', + dd : '%d jours', + M : 'un mois', + MM : '%d mois', + y : 'un an', + yy : '%d ans' + }, + ordinalParse: /\d{1,2}(er|e)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : 'e'); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,55 @@
+//! moment.js locale configuration +//! locale : French [fr] +//! author : John Fischer : https://github.com/jfroffice + +import moment from '../moment'; + +export default moment.defineLocale('fr', { + months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), + monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), + monthsParseExact : true, + weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), + weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), + weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Aujourd\'hui à] LT', + nextDay: '[Demain à] LT', + nextWeek: 'dddd [à] LT', + lastDay: '[Hier à] LT', + lastWeek: 'dddd [dernier à] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dans %s', + past : 'il y a %s', + s : 'quelques secondes', + m : 'une minute', + mm : '%d minutes', + h : 'une heure', + hh : '%d heures', + d : 'un jour', + dd : '%d jours', + M : 'un mois', + MM : '%d mois', + y : 'un an', + yy : '%d ans' + }, + ordinalParse: /\d{1,2}(er|)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : ''); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,64 @@
+//! moment.js locale configuration +//! locale : Frisian [fy] +//! author : Robin van der Vliet : https://github.com/robin0van0der0v + +import moment from '../moment'; + +var monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_'), + monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'); + +export default moment.defineLocale('fy', { + months : 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShortWithoutDots[m.month()]; + } else { + return monthsShortWithDots[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split('_'), + weekdaysShort : 'si._mo._ti._wo._to._fr._so.'.split('_'), + weekdaysMin : 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[hjoed om] LT', + nextDay: '[moarn om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[juster om] LT', + lastWeek: '[ôfrûne] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'oer %s', + past : '%s lyn', + s : 'in pear sekonden', + m : 'ien minút', + mm : '%d minuten', + h : 'ien oere', + hh : '%d oeren', + d : 'ien dei', + dd : '%d dagen', + M : 'ien moanne', + MM : '%d moannen', + y : 'ien jier', + yy : '%d jierren' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,67 @@
+//! moment.js locale configuration +//! locale : Scottish Gaelic [gd] +//! author : Jon Ashdown : https://github.com/jonashdown + +import moment from '../moment'; + +var months = [ + 'Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean', 'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal', 'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd' +]; + +var monthsShort = ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh']; + +var weekdays = ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne']; + +var weekdaysShort = ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis']; + +var weekdaysMin = ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa']; + +export default moment.defineLocale('gd', { + months : months, + monthsShort : monthsShort, + monthsParseExact : true, + weekdays : weekdays, + weekdaysShort : weekdaysShort, + weekdaysMin : weekdaysMin, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[An-diugh aig] LT', + nextDay : '[A-màireach aig] LT', + nextWeek : 'dddd [aig] LT', + lastDay : '[An-dè aig] LT', + lastWeek : 'dddd [seo chaidh] [aig] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'ann an %s', + past : 'bho chionn %s', + s : 'beagan diogan', + m : 'mionaid', + mm : '%d mionaidean', + h : 'uair', + hh : '%d uairean', + d : 'latha', + dd : '%d latha', + M : 'mìos', + MM : '%d mìosan', + y : 'bliadhna', + yy : '%d bliadhna' + }, + ordinalParse : /\d{1,2}(d|na|mh)/, + ordinal : function (number) { + var output = number === 1 ? 'd' : number % 10 === 2 ? 'na' : 'mh'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,68 @@
+//! moment.js locale configuration +//! locale : Galician [gl] +//! author : Juan G. Hurtado : https://github.com/juanghurtado + +import moment from '../moment'; + +export default moment.defineLocale('gl', { + months : 'Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro'.split('_'), + monthsShort : 'Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.'.split('_'), + monthsParseExact: true, + weekdays : 'Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado'.split('_'), + weekdaysShort : 'Dom._Lun._Mar._Mér._Xov._Ven._Sáb.'.split('_'), + weekdaysMin : 'Do_Lu_Ma_Mé_Xo_Ve_Sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd D MMMM YYYY H:mm' + }, + calendar : { + sameDay : function () { + return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; + }, + nextDay : function () { + return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; + }, + nextWeek : function () { + return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + lastDay : function () { + return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT'; + }, + lastWeek : function () { + return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; + }, + sameElse : 'L' + }, + relativeTime : { + future : function (str) { + if (str === 'uns segundos') { + return 'nuns segundos'; + } + return 'en ' + str; + }, + past : 'hai %s', + s : 'uns segundos', + m : 'un minuto', + mm : '%d minutos', + h : 'unha hora', + hh : '%d horas', + d : 'un día', + dd : '%d días', + M : 'un mes', + MM : '%d meses', + y : 'un ano', + yy : '%d anos' + }, + ordinalParse : /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,90 @@
+//! moment.js locale configuration +//! locale : Hebrew [he] +//! author : Tomer Cohen : https://github.com/tomer +//! author : Moshe Simantov : https://github.com/DevelopmentIL +//! author : Tal Ater : https://github.com/TalAter + +import moment from '../moment'; + +export default moment.defineLocale('he', { + months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'), + monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'), + weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'), + weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'), + weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [ב]MMMM YYYY', + LLL : 'D [ב]MMMM YYYY HH:mm', + LLLL : 'dddd, D [ב]MMMM YYYY HH:mm', + l : 'D/M/YYYY', + ll : 'D MMM YYYY', + lll : 'D MMM YYYY HH:mm', + llll : 'ddd, D MMM YYYY HH:mm' + }, + calendar : { + sameDay : '[היום ב־]LT', + nextDay : '[מחר ב־]LT', + nextWeek : 'dddd [בשעה] LT', + lastDay : '[אתמול ב־]LT', + lastWeek : '[ביום] dddd [האחרון בשעה] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'בעוד %s', + past : 'לפני %s', + s : 'מספר שניות', + m : 'דקה', + mm : '%d דקות', + h : 'שעה', + hh : function (number) { + if (number === 2) { + return 'שעתיים'; + } + return number + ' שעות'; + }, + d : 'יום', + dd : function (number) { + if (number === 2) { + return 'יומיים'; + } + return number + ' ימים'; + }, + M : 'חודש', + MM : function (number) { + if (number === 2) { + return 'חודשיים'; + } + return number + ' חודשים'; + }, + y : 'שנה', + yy : function (number) { + if (number === 2) { + return 'שנתיים'; + } else if (number % 10 === 0 && number !== 10) { + return number + ' שנה'; + } + return number + ' שנים'; + } + }, + meridiemParse: /אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i, + isPM : function (input) { + return /^(אחה"צ|אחרי הצהריים|בערב)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 5) { + return 'לפנות בוקר'; + } else if (hour < 10) { + return 'בבוקר'; + } else if (hour < 12) { + return isLower ? 'לפנה"צ' : 'לפני הצהריים'; + } else if (hour < 18) { + return isLower ? 'אחה"צ' : 'אחרי הצהריים'; + } else { + return 'בערב'; + } + } +}); +
@@ -0,0 +1,115 @@
+//! moment.js locale configuration +//! locale : Hindi [hi] +//! author : Mayank Singhal : https://github.com/mayanksinghal + +import moment from '../moment'; + +var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' +}, +numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' +}; + +export default moment.defineLocale('hi', { + months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'), + monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'), + monthsParseExact: true, + weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm बजे', + LTS : 'A h:mm:ss बजे', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm बजे', + LLLL : 'dddd, D MMMM YYYY, A h:mm बजे' + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[कल] LT', + nextWeek : 'dddd, LT', + lastDay : '[कल] LT', + lastWeek : '[पिछले] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s में', + past : '%s पहले', + s : 'कुछ ही क्षण', + m : 'एक मिनट', + mm : '%d मिनट', + h : 'एक घंटा', + hh : '%d घंटे', + d : 'एक दिन', + dd : '%d दिन', + M : 'एक महीने', + MM : '%d महीने', + y : 'एक वर्ष', + yy : '%d वर्ष' + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + // Hindi notation for meridiems are quite fuzzy in practice. While there exists + // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi. + meridiemParse: /रात|सुबह|दोपहर|शाम/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सुबह') { + return hour; + } else if (meridiem === 'दोपहर') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'शाम') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'रात'; + } else if (hour < 10) { + return 'सुबह'; + } else if (hour < 17) { + return 'दोपहर'; + } else if (hour < 20) { + return 'शाम'; + } else { + return 'रात'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,136 @@
+//! moment.js locale configuration +//! locale : Croatian [hr] +//! author : Bojan Marković : https://github.com/bmarkovic + +import moment from '../moment'; + +function translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } +} + +export default moment.defineLocale('hr', { + months : { + format: 'siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca'.split('_'), + standalone: 'siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_') + }, + monthsShort : 'sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'), + monthsParseExact: true, + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : translate, + mm : translate, + h : translate, + hh : translate, + d : 'dan', + dd : translate, + M : 'mjesec', + MM : translate, + y : 'godinu', + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,100 @@
+//! moment.js locale configuration +//! locale : Hungarian [hu] +//! author : Adam Brunner : https://github.com/adambrunner + +import moment from '../moment'; + +var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' '); +function translate(number, withoutSuffix, key, isFuture) { + var num = number, + suffix; + switch (key) { + case 's': + return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce'; + case 'm': + return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce'); + case 'mm': + return num + (isFuture || withoutSuffix ? ' perc' : ' perce'); + case 'h': + return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája'); + case 'hh': + return num + (isFuture || withoutSuffix ? ' óra' : ' órája'); + case 'd': + return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja'); + case 'dd': + return num + (isFuture || withoutSuffix ? ' nap' : ' napja'); + case 'M': + return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); + case 'MM': + return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja'); + case 'y': + return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve'); + case 'yy': + return num + (isFuture || withoutSuffix ? ' év' : ' éve'); + } + return ''; +} +function week(isFuture) { + return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]'; +} + +export default moment.defineLocale('hu', { + months : 'január_február_március_április_május_június_július_augusztus_szeptember_október_november_december'.split('_'), + monthsShort : 'jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec'.split('_'), + weekdays : 'vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat'.split('_'), + weekdaysShort : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'), + weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'YYYY.MM.DD.', + LL : 'YYYY. MMMM D.', + LLL : 'YYYY. MMMM D. H:mm', + LLLL : 'YYYY. MMMM D., dddd H:mm' + }, + meridiemParse: /de|du/i, + isPM: function (input) { + return input.charAt(1).toLowerCase() === 'u'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower === true ? 'de' : 'DE'; + } else { + return isLower === true ? 'du' : 'DU'; + } + }, + calendar : { + sameDay : '[ma] LT[-kor]', + nextDay : '[holnap] LT[-kor]', + nextWeek : function () { + return week.call(this, true); + }, + lastDay : '[tegnap] LT[-kor]', + lastWeek : function () { + return week.call(this, false); + }, + sameElse : 'L' + }, + relativeTime : { + future : '%s múlva', + past : '%s', + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,86 @@
+//! moment.js locale configuration +//! locale : Armenian [hy-am] +//! author : Armendarabyan : https://github.com/armendarabyan + +import moment from '../moment'; + +export default moment.defineLocale('hy-am', { + months : { + format: 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_'), + standalone: 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_') + }, + monthsShort : 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'), + weekdays : 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_'), + weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY թ.', + LLL : 'D MMMM YYYY թ., HH:mm', + LLLL : 'dddd, D MMMM YYYY թ., HH:mm' + }, + calendar : { + sameDay: '[այսօր] LT', + nextDay: '[վաղը] LT', + lastDay: '[երեկ] LT', + nextWeek: function () { + return 'dddd [օրը ժամը] LT'; + }, + lastWeek: function () { + return '[անցած] dddd [օրը ժամը] LT'; + }, + sameElse: 'L' + }, + relativeTime : { + future : '%s հետո', + past : '%s առաջ', + s : 'մի քանի վայրկյան', + m : 'րոպե', + mm : '%d րոպե', + h : 'ժամ', + hh : '%d ժամ', + d : 'օր', + dd : '%d օր', + M : 'ամիս', + MM : '%d ամիս', + y : 'տարի', + yy : '%d տարի' + }, + meridiemParse: /գիշերվա|առավոտվա|ցերեկվա|երեկոյան/, + isPM: function (input) { + return /^(ցերեկվա|երեկոյան)$/.test(input); + }, + meridiem : function (hour) { + if (hour < 4) { + return 'գիշերվա'; + } else if (hour < 12) { + return 'առավոտվա'; + } else if (hour < 17) { + return 'ցերեկվա'; + } else { + return 'երեկոյան'; + } + }, + ordinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/, + ordinal: function (number, period) { + switch (period) { + case 'DDD': + case 'w': + case 'W': + case 'DDDo': + if (number === 1) { + return number + '-ին'; + } + return number + '-րդ'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,74 @@
+//! moment.js locale configuration +//! locale : Indonesian [id] +//! author : Mohammad Satrio Utomo : https://github.com/tyok +//! reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan + +import moment from '../moment'; + +export default moment.defineLocale('id', { + months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu'.split('_'), + weekdaysShort : 'Min_Sen_Sel_Rab_Kam_Jum_Sab'.split('_'), + weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sb'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /pagi|siang|sore|malam/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'siang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sore' || meridiem === 'malam') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'siang'; + } else if (hours < 19) { + return 'sore'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Besok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kemarin pukul] LT', + lastWeek : 'dddd [lalu pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'dalam %s', + past : '%s yang lalu', + s : 'beberapa detik', + m : 'semenit', + mm : '%d menit', + h : 'sejam', + hh : '%d jam', + d : 'sehari', + dd : '%d hari', + M : 'sebulan', + MM : '%d bulan', + y : 'setahun', + yy : '%d tahun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,118 @@
+//! moment.js locale configuration +//! locale : Icelandic [is] +//! author : Hinrik Örn Sigurðsson : https://github.com/hinrik + +import moment from '../moment'; + +function plural(n) { + if (n % 100 === 11) { + return true; + } else if (n % 10 === 1) { + return false; + } + return true; +} +function translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum'; + case 'm': + return withoutSuffix ? 'mínúta' : 'mínútu'; + case 'mm': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum'); + } else if (withoutSuffix) { + return result + 'mínúta'; + } + return result + 'mínútu'; + case 'hh': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum'); + } + return result + 'klukkustund'; + case 'd': + if (withoutSuffix) { + return 'dagur'; + } + return isFuture ? 'dag' : 'degi'; + case 'dd': + if (plural(number)) { + if (withoutSuffix) { + return result + 'dagar'; + } + return result + (isFuture ? 'daga' : 'dögum'); + } else if (withoutSuffix) { + return result + 'dagur'; + } + return result + (isFuture ? 'dag' : 'degi'); + case 'M': + if (withoutSuffix) { + return 'mánuður'; + } + return isFuture ? 'mánuð' : 'mánuði'; + case 'MM': + if (plural(number)) { + if (withoutSuffix) { + return result + 'mánuðir'; + } + return result + (isFuture ? 'mánuði' : 'mánuðum'); + } else if (withoutSuffix) { + return result + 'mánuður'; + } + return result + (isFuture ? 'mánuð' : 'mánuði'); + case 'y': + return withoutSuffix || isFuture ? 'ár' : 'ári'; + case 'yy': + if (plural(number)) { + return result + (withoutSuffix || isFuture ? 'ár' : 'árum'); + } + return result + (withoutSuffix || isFuture ? 'ár' : 'ári'); + } +} + +export default moment.defineLocale('is', { + months : 'janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des'.split('_'), + weekdays : 'sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur'.split('_'), + weekdaysShort : 'sun_mán_þri_mið_fim_fös_lau'.split('_'), + weekdaysMin : 'Su_Má_Þr_Mi_Fi_Fö_La'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] H:mm', + LLLL : 'dddd, D. MMMM YYYY [kl.] H:mm' + }, + calendar : { + sameDay : '[í dag kl.] LT', + nextDay : '[á morgun kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[í gær kl.] LT', + lastWeek : '[síðasta] dddd [kl.] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'eftir %s', + past : 'fyrir %s síðan', + s : translate, + m : translate, + mm : translate, + h : 'klukkustund', + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,61 @@
+//! moment.js locale configuration +//! locale : Italian [it] +//! author : Lorenzo : https://github.com/aliem +//! author: Mattia Larentis: https://github.com/nostalgiaz + +import moment from '../moment'; + +export default moment.defineLocale('it', { + months : 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split('_'), + monthsShort : 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'), + weekdays : 'Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato'.split('_'), + weekdaysShort : 'Dom_Lun_Mar_Mer_Gio_Ven_Sab'.split('_'), + weekdaysMin : 'Do_Lu_Ma_Me_Gi_Ve_Sa'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Oggi alle] LT', + nextDay: '[Domani alle] LT', + nextWeek: 'dddd [alle] LT', + lastDay: '[Ieri alle] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[la scorsa] dddd [alle] LT'; + default: + return '[lo scorso] dddd [alle] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : function (s) { + return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s; + }, + past : '%s fa', + s : 'alcuni secondi', + m : 'un minuto', + mm : '%d minuti', + h : 'un\'ora', + hh : '%d ore', + d : 'un giorno', + dd : '%d giorni', + M : 'un mese', + MM : '%d mesi', + y : 'un anno', + yy : '%d anni' + }, + ordinalParse : /\d{1,2}º/, + ordinal: '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,67 @@
+//! moment.js locale configuration +//! locale : Japanese [ja] +//! author : LI Long : https://github.com/baryon + +import moment from '../moment'; + +export default moment.defineLocale('ja', { + months : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + weekdays : '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'), + weekdaysShort : '日_月_火_水_木_金_土'.split('_'), + weekdaysMin : '日_月_火_水_木_金_土'.split('_'), + longDateFormat : { + LT : 'Ah時m分', + LTS : 'Ah時m分s秒', + L : 'YYYY/MM/DD', + LL : 'YYYY年M月D日', + LLL : 'YYYY年M月D日Ah時m分', + LLLL : 'YYYY年M月D日Ah時m分 dddd' + }, + meridiemParse: /午前|午後/i, + isPM : function (input) { + return input === '午後'; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return '午前'; + } else { + return '午後'; + } + }, + calendar : { + sameDay : '[今日] LT', + nextDay : '[明日] LT', + nextWeek : '[来週]dddd LT', + lastDay : '[昨日] LT', + lastWeek : '[前週]dddd LT', + sameElse : 'L' + }, + ordinalParse : /\d{1,2}日/, + ordinal : function (number, period) { + switch (period) { + case 'd': + case 'D': + case 'DDD': + return number + '日'; + default: + return number; + } + }, + relativeTime : { + future : '%s後', + past : '%s前', + s : '数秒', + m : '1分', + mm : '%d分', + h : '1時間', + hh : '%d時間', + d : '1日', + dd : '%d日', + M : '1ヶ月', + MM : '%dヶ月', + y : '1年', + yy : '%d年' + } +}); +
@@ -0,0 +1,73 @@
+//! moment.js locale configuration +//! locale : Japanese [jv] +//! author : Rony Lantip : https://github.com/lantip +//! reference: http://jv.wikipedia.org/wiki/Basa_Jawa + +import moment from '../moment'; + +export default moment.defineLocale('jv', { + months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des'.split('_'), + weekdays : 'Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu'.split('_'), + weekdaysShort : 'Min_Sen_Sel_Reb_Kem_Jem_Sep'.split('_'), + weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sp'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /enjing|siyang|sonten|ndalu/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'enjing') { + return hour; + } else if (meridiem === 'siyang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sonten' || meridiem === 'ndalu') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'enjing'; + } else if (hours < 15) { + return 'siyang'; + } else if (hours < 19) { + return 'sonten'; + } else { + return 'ndalu'; + } + }, + calendar : { + sameDay : '[Dinten puniko pukul] LT', + nextDay : '[Mbenjang pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kala wingi pukul] LT', + lastWeek : 'dddd [kepengker pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'wonten ing %s', + past : '%s ingkang kepengker', + s : 'sawetawis detik', + m : 'setunggal menit', + mm : '%d menit', + h : 'setunggal jam', + hh : '%d jam', + d : 'sedinten', + dd : '%d dinten', + M : 'sewulan', + MM : '%d wulan', + y : 'setaun', + yy : '%d taun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +});
@@ -0,0 +1,80 @@
+//! moment.js locale configuration +//! locale : Georgian [ka] +//! author : Irakli Janiashvili : https://github.com/irakli-janiashvili + +import moment from '../moment'; + +export default moment.defineLocale('ka', { + months : { + standalone: 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'), + format: 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_') + }, + monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'), + weekdays : { + standalone: 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'), + format: 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_'), + isFormat: /(წინა|შემდეგ)/ + }, + weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'), + weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[დღეს] LT[-ზე]', + nextDay : '[ხვალ] LT[-ზე]', + lastDay : '[გუშინ] LT[-ზე]', + nextWeek : '[შემდეგ] dddd LT[-ზე]', + lastWeek : '[წინა] dddd LT-ზე', + sameElse : 'L' + }, + relativeTime : { + future : function (s) { + return (/(წამი|წუთი|საათი|წელი)/).test(s) ? + s.replace(/ი$/, 'ში') : + s + 'ში'; + }, + past : function (s) { + if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) { + return s.replace(/(ი|ე)$/, 'ის წინ'); + } + if ((/წელი/).test(s)) { + return s.replace(/წელი$/, 'წლის წინ'); + } + }, + s : 'რამდენიმე წამი', + m : 'წუთი', + mm : '%d წუთი', + h : 'საათი', + hh : '%d საათი', + d : 'დღე', + dd : '%d დღე', + M : 'თვე', + MM : '%d თვე', + y : 'წელი', + yy : '%d წელი' + }, + ordinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/, + ordinal : function (number) { + if (number === 0) { + return number; + } + if (number === 1) { + return number + '-ლი'; + } + if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) { + return 'მე-' + number; + } + return number + '-ე'; + }, + week : { + dow : 1, + doy : 7 + } +}); +
@@ -0,0 +1,77 @@
+//! moment.js locale configuration +//! locale : Kazakh [kk] +//! authors : Nurlan Rakhimzhanov : https://github.com/nurlan + +import moment from '../moment'; + +var suffixes = { + 0: '-ші', + 1: '-ші', + 2: '-ші', + 3: '-ші', + 4: '-ші', + 5: '-ші', + 6: '-шы', + 7: '-ші', + 8: '-ші', + 9: '-шы', + 10: '-шы', + 20: '-шы', + 30: '-шы', + 40: '-шы', + 50: '-ші', + 60: '-шы', + 70: '-ші', + 80: '-ші', + 90: '-шы', + 100: '-ші' +}; + +export default moment.defineLocale('kk', { + months : 'қаңтар_ақпан_наурыз_сәуір_мамыр_маусым_шілде_тамыз_қыркүйек_қазан_қараша_желтоқсан'.split('_'), + monthsShort : 'қаң_ақп_нау_сәу_мам_мау_шіл_там_қыр_қаз_қар_жел'.split('_'), + weekdays : 'жексенбі_дүйсенбі_сейсенбі_сәрсенбі_бейсенбі_жұма_сенбі'.split('_'), + weekdaysShort : 'жек_дүй_сей_сәр_бей_жұм_сен'.split('_'), + weekdaysMin : 'жк_дй_сй_ср_бй_жм_сн'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Бүгін сағат] LT', + nextDay : '[Ертең сағат] LT', + nextWeek : 'dddd [сағат] LT', + lastDay : '[Кеше сағат] LT', + lastWeek : '[Өткен аптаның] dddd [сағат] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ішінде', + past : '%s бұрын', + s : 'бірнеше секунд', + m : 'бір минут', + mm : '%d минут', + h : 'бір сағат', + hh : '%d сағат', + d : 'бір күн', + dd : '%d күн', + M : 'бір ай', + MM : '%d ай', + y : 'бір жыл', + yy : '%d жыл' + }, + ordinalParse: /\d{1,2}-(ші|шы)/, + ordinal : function (number) { + var a = number % 10, + b = number >= 100 ? 100 : null; + return number + (suffixes[number] || suffixes[a] || suffixes[b]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +});
@@ -0,0 +1,49 @@
+//! moment.js locale configuration +//! locale : Cambodian [km] +//! author : Kruy Vanna : https://github.com/kruyvanna + +import moment from '../moment'; + +export default moment.defineLocale('km', { + months: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + monthsShort: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + longDateFormat: { + LT: 'HH:mm', + LTS : 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd, D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[ថ្ងៃនេះ ម៉ោង] LT', + nextDay: '[ស្អែក ម៉ោង] LT', + nextWeek: 'dddd [ម៉ោង] LT', + lastDay: '[ម្សិលមិញ ម៉ោង] LT', + lastWeek: 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT', + sameElse: 'L' + }, + relativeTime: { + future: '%sទៀត', + past: '%sមុន', + s: 'ប៉ុន្មានវិនាទី', + m: 'មួយនាទី', + mm: '%d នាទី', + h: 'មួយម៉ោង', + hh: '%d ម៉ោង', + d: 'មួយថ្ងៃ', + dd: '%d ថ្ងៃ', + M: 'មួយខែ', + MM: '%d ខែ', + y: 'មួយឆ្នាំ', + yy: '%d ឆ្នាំ' + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,59 @@
+//! moment.js locale configuration +//! locale : Korean [ko] +//! +//! authors +//! +//! - Kyungwook, Park : https://github.com/kyungw00k +//! - Jeeeyul Lee <jeeeyul@gmail.com> + +import moment from '../moment'; + +export default moment.defineLocale('ko', { + months : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'), + monthsShort : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'), + weekdays : '일요일_월요일_화요일_수요일_목요일_금요일_토요일'.split('_'), + weekdaysShort : '일_월_화_수_목_금_토'.split('_'), + weekdaysMin : '일_월_화_수_목_금_토'.split('_'), + longDateFormat : { + LT : 'A h시 m분', + LTS : 'A h시 m분 s초', + L : 'YYYY.MM.DD', + LL : 'YYYY년 MMMM D일', + LLL : 'YYYY년 MMMM D일 A h시 m분', + LLLL : 'YYYY년 MMMM D일 dddd A h시 m분' + }, + calendar : { + sameDay : '오늘 LT', + nextDay : '내일 LT', + nextWeek : 'dddd LT', + lastDay : '어제 LT', + lastWeek : '지난주 dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s 후', + past : '%s 전', + s : '몇 초', + ss : '%d초', + m : '일분', + mm : '%d분', + h : '한 시간', + hh : '%d시간', + d : '하루', + dd : '%d일', + M : '한 달', + MM : '%d달', + y : '일 년', + yy : '%d년' + }, + ordinalParse : /\d{1,2}일/, + ordinal : '%d일', + meridiemParse : /오전|오후/, + isPM : function (token) { + return token === '오후'; + }, + meridiem : function (hour, minute, isUpper) { + return hour < 12 ? '오전' : '오후'; + } +}); +
@@ -0,0 +1,78 @@
+//! moment.js locale configuration +//! locale : Kyrgyz [ky] +//! author : Chyngyz Arystan uulu : https://github.com/chyngyz + + +import moment from '../moment'; + +var suffixes = { + 0: '-чү', + 1: '-чи', + 2: '-чи', + 3: '-чү', + 4: '-чү', + 5: '-чи', + 6: '-чы', + 7: '-чи', + 8: '-чи', + 9: '-чу', + 10: '-чу', + 20: '-чы', + 30: '-чу', + 40: '-чы', + 50: '-чү', + 60: '-чы', + 70: '-чи', + 80: '-чи', + 90: '-чу', + 100: '-чү' +}; + +export default moment.defineLocale('ky', { + months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + monthsShort : 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'), + weekdays : 'Жекшемби_Дүйшөмбү_Шейшемби_Шаршемби_Бейшемби_Жума_Ишемби'.split('_'), + weekdaysShort : 'Жек_Дүй_Шей_Шар_Бей_Жум_Ише'.split('_'), + weekdaysMin : 'Жк_Дй_Шй_Шр_Бй_Жм_Иш'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Бүгүн саат] LT', + nextDay : '[Эртең саат] LT', + nextWeek : 'dddd [саат] LT', + lastDay : '[Кече саат] LT', + lastWeek : '[Өткен аптанын] dddd [күнү] [саат] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ичинде', + past : '%s мурун', + s : 'бирнече секунд', + m : 'бир мүнөт', + mm : '%d мүнөт', + h : 'бир саат', + hh : '%d саат', + d : 'бир күн', + dd : '%d күн', + M : 'бир ай', + MM : '%d ай', + y : 'бир жыл', + yy : '%d жыл' + }, + ordinalParse: /\d{1,2}-(чи|чы|чү|чу)/, + ordinal : function (number) { + var a = number % 10, + b = number >= 100 ? 100 : null; + return number + (suffixes[number] || suffixes[a] || suffixes[b]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +});
@@ -0,0 +1,127 @@
+//! moment.js locale configuration +//! locale : Luxembourgish [lb] +//! author : mweimerskirch : https://github.com/mweimerskirch, David Raison : https://github.com/kwisatz + +import moment from '../moment'; + +function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eng Minutt', 'enger Minutt'], + 'h': ['eng Stonn', 'enger Stonn'], + 'd': ['een Dag', 'engem Dag'], + 'M': ['ee Mount', 'engem Mount'], + 'y': ['ee Joer', 'engem Joer'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; +} +function processFutureTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'a ' + string; + } + return 'an ' + string; +} +function processPastTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'viru ' + string; + } + return 'virun ' + string; +} +/** + * Returns true if the word before the given number loses the '-n' ending. + * e.g. 'an 10 Deeg' but 'a 5 Deeg' + * + * @param number {integer} + * @returns {boolean} + */ +function eifelerRegelAppliesToNumber(number) { + number = parseInt(number, 10); + if (isNaN(number)) { + return false; + } + if (number < 0) { + // Negative Number --> always true + return true; + } else if (number < 10) { + // Only 1 digit + if (4 <= number && number <= 7) { + return true; + } + return false; + } else if (number < 100) { + // 2 digits + var lastDigit = number % 10, firstDigit = number / 10; + if (lastDigit === 0) { + return eifelerRegelAppliesToNumber(firstDigit); + } + return eifelerRegelAppliesToNumber(lastDigit); + } else if (number < 10000) { + // 3 or 4 digits --> recursively check first digit + while (number >= 10) { + number = number / 10; + } + return eifelerRegelAppliesToNumber(number); + } else { + // Anything larger than 4 digits: recursively check first n-3 digits + number = number / 1000; + return eifelerRegelAppliesToNumber(number); + } +} + +export default moment.defineLocale('lb', { + months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + monthsParseExact : true, + weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'), + weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'), + weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm [Auer]', + LTS: 'H:mm:ss [Auer]', + L: 'DD.MM.YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm [Auer]', + LLLL: 'dddd, D. MMMM YYYY H:mm [Auer]' + }, + calendar: { + sameDay: '[Haut um] LT', + sameElse: 'L', + nextDay: '[Muer um] LT', + nextWeek: 'dddd [um] LT', + lastDay: '[Gëschter um] LT', + lastWeek: function () { + // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule + switch (this.day()) { + case 2: + case 4: + return '[Leschten] dddd [um] LT'; + default: + return '[Leschte] dddd [um] LT'; + } + } + }, + relativeTime : { + future : processFutureTime, + past : processPastTime, + s : 'e puer Sekonnen', + m : processRelativeTime, + mm : '%d Minutten', + h : processRelativeTime, + hh : '%d Stonnen', + d : processRelativeTime, + dd : '%d Deeg', + M : processRelativeTime, + MM : '%d Méint', + y : processRelativeTime, + yy : '%d Joer' + }, + ordinalParse: /\d{1,2}\./, + ordinal: '%d.', + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,61 @@
+//! moment.js locale configuration +//! locale : Lao [lo] +//! author : Ryan Hart : https://github.com/ryanhart2 + +import moment from '../moment'; + +export default moment.defineLocale('lo', { + months : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'), + monthsShort : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'), + weekdays : 'ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'), + weekdaysShort : 'ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'), + weekdaysMin : 'ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'ວັນdddd D MMMM YYYY HH:mm' + }, + meridiemParse: /ຕອນເຊົ້າ|ຕອນແລງ/, + isPM: function (input) { + return input === 'ຕອນແລງ'; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ຕອນເຊົ້າ'; + } else { + return 'ຕອນແລງ'; + } + }, + calendar : { + sameDay : '[ມື້ນີ້ເວລາ] LT', + nextDay : '[ມື້ອື່ນເວລາ] LT', + nextWeek : '[ວັນ]dddd[ໜ້າເວລາ] LT', + lastDay : '[ມື້ວານນີ້ເວລາ] LT', + lastWeek : '[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'ອີກ %s', + past : '%sຜ່ານມາ', + s : 'ບໍ່ເທົ່າໃດວິນາທີ', + m : '1 ນາທີ', + mm : '%d ນາທີ', + h : '1 ຊົ່ວໂມງ', + hh : '%d ຊົ່ວໂມງ', + d : '1 ມື້', + dd : '%d ມື້', + M : '1 ເດືອນ', + MM : '%d ເດືອນ', + y : '1 ປີ', + yy : '%d ປີ' + }, + ordinalParse: /(ທີ່)\d{1,2}/, + ordinal : function (number) { + return 'ທີ່' + number; + } +}); +
@@ -0,0 +1,108 @@
+//! moment.js locale configuration +//! locale : Lithuanian [lt] +//! author : Mindaugas Mozūras : https://github.com/mmozuras + +import moment from '../moment'; + +var units = { + 'm' : 'minutė_minutės_minutę', + 'mm': 'minutės_minučių_minutes', + 'h' : 'valanda_valandos_valandą', + 'hh': 'valandos_valandų_valandas', + 'd' : 'diena_dienos_dieną', + 'dd': 'dienos_dienų_dienas', + 'M' : 'mėnuo_mėnesio_mėnesį', + 'MM': 'mėnesiai_mėnesių_mėnesius', + 'y' : 'metai_metų_metus', + 'yy': 'metai_metų_metus' +}; +function translateSeconds(number, withoutSuffix, key, isFuture) { + if (withoutSuffix) { + return 'kelios sekundės'; + } else { + return isFuture ? 'kelių sekundžių' : 'kelias sekundes'; + } +} +function translateSingular(number, withoutSuffix, key, isFuture) { + return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]); +} +function special(number) { + return number % 10 === 0 || (number > 10 && number < 20); +} +function forms(key) { + return units[key].split('_'); +} +function translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + if (number === 1) { + return result + translateSingular(number, withoutSuffix, key[0], isFuture); + } else if (withoutSuffix) { + return result + (special(number) ? forms(key)[1] : forms(key)[0]); + } else { + if (isFuture) { + return result + forms(key)[1]; + } else { + return result + (special(number) ? forms(key)[1] : forms(key)[2]); + } + } +} +export default moment.defineLocale('lt', { + months : { + format: 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'), + standalone: 'sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis'.split('_'), + isFormat: /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?|MMMM?(\[[^\[\]]*\]|\s+)+D[oD]?/ + }, + monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'), + weekdays : { + format: 'sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį'.split('_'), + standalone: 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_'), + isFormat: /dddd HH:mm/ + }, + weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'), + weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'YYYY [m.] MMMM D [d.]', + LLL : 'YYYY [m.] MMMM D [d.], HH:mm [val.]', + LLLL : 'YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]', + l : 'YYYY-MM-DD', + ll : 'YYYY [m.] MMMM D [d.]', + lll : 'YYYY [m.] MMMM D [d.], HH:mm [val.]', + llll : 'YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]' + }, + calendar : { + sameDay : '[Šiandien] LT', + nextDay : '[Rytoj] LT', + nextWeek : 'dddd LT', + lastDay : '[Vakar] LT', + lastWeek : '[Praėjusį] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : 'po %s', + past : 'prieš %s', + s : translateSeconds, + m : translateSingular, + mm : translate, + h : translateSingular, + hh : translate, + d : translateSingular, + dd : translate, + M : translateSingular, + MM : translate, + y : translateSingular, + yy : translate + }, + ordinalParse: /\d{1,2}-oji/, + ordinal : function (number) { + return number + '-oji'; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,88 @@
+//! moment.js locale configuration +//! locale : Latvian [lv] +//! author : Kristaps Karlsons : https://github.com/skakri +//! author : Jānis Elmeris : https://github.com/JanisE + +import moment from '../moment'; + +var units = { + 'm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'mm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'h': 'stundas_stundām_stunda_stundas'.split('_'), + 'hh': 'stundas_stundām_stunda_stundas'.split('_'), + 'd': 'dienas_dienām_diena_dienas'.split('_'), + 'dd': 'dienas_dienām_diena_dienas'.split('_'), + 'M': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'MM': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'y': 'gada_gadiem_gads_gadi'.split('_'), + 'yy': 'gada_gadiem_gads_gadi'.split('_') +}; +/** + * @param withoutSuffix boolean true = a length of time; false = before/after a period of time. + */ +function format(forms, number, withoutSuffix) { + if (withoutSuffix) { + // E.g. "21 minūte", "3 minūtes". + return number % 10 === 1 && number % 100 !== 11 ? forms[2] : forms[3]; + } else { + // E.g. "21 minūtes" as in "pēc 21 minūtes". + // E.g. "3 minūtēm" as in "pēc 3 minūtēm". + return number % 10 === 1 && number % 100 !== 11 ? forms[0] : forms[1]; + } +} +function relativeTimeWithPlural(number, withoutSuffix, key) { + return number + ' ' + format(units[key], number, withoutSuffix); +} +function relativeTimeWithSingular(number, withoutSuffix, key) { + return format(units[key], number, withoutSuffix); +} +function relativeSeconds(number, withoutSuffix) { + return withoutSuffix ? 'dažas sekundes' : 'dažām sekundēm'; +} + +export default moment.defineLocale('lv', { + months : 'janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec'.split('_'), + weekdays : 'svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena'.split('_'), + weekdaysShort : 'Sv_P_O_T_C_Pk_S'.split('_'), + weekdaysMin : 'Sv_P_O_T_C_Pk_S'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY.', + LL : 'YYYY. [gada] D. MMMM', + LLL : 'YYYY. [gada] D. MMMM, HH:mm', + LLLL : 'YYYY. [gada] D. MMMM, dddd, HH:mm' + }, + calendar : { + sameDay : '[Šodien pulksten] LT', + nextDay : '[Rīt pulksten] LT', + nextWeek : 'dddd [pulksten] LT', + lastDay : '[Vakar pulksten] LT', + lastWeek : '[Pagājušā] dddd [pulksten] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'pēc %s', + past : 'pirms %s', + s : relativeSeconds, + m : relativeTimeWithSingular, + mm : relativeTimeWithPlural, + h : relativeTimeWithSingular, + hh : relativeTimeWithPlural, + d : relativeTimeWithSingular, + dd : relativeTimeWithPlural, + M : relativeTimeWithSingular, + MM : relativeTimeWithPlural, + y : relativeTimeWithSingular, + yy : relativeTimeWithPlural + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,101 @@
+//! moment.js locale configuration +//! locale : Montenegrin [me] +//! author : Miodrag Nikač <miodrag@restartit.me> : https://github.com/miodragnikac + +import moment from '../moment'; + +var translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jednog minuta'], + mm: ['minut', 'minuta', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mjesec', 'mjeseca', 'mjeseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + translator.correctGrammaticalCase(number, wordKey); + } + } +}; + +export default moment.defineLocale('me', { + months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'), + monthsParseExact : true, + weekdays: 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort: 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm', + LTS : 'H:mm:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm', + LLLL: 'dddd, D. MMMM YYYY H:mm' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sjutra u] LT', + + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedjelje] [u] LT', + '[prošlog] [ponedjeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srijede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'nekoliko sekundi', + m : translator.translate, + mm : translator.translate, + h : translator.translate, + hh : translator.translate, + d : 'dan', + dd : translator.translate, + M : 'mjesec', + MM : translator.translate, + y : 'godinu', + yy : translator.translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +});
@@ -0,0 +1,81 @@
+//! moment.js locale configuration +//! locale : Macedonian [mk] +//! author : Borislav Mickov : https://github.com/B0k0 + +import moment from '../moment'; + +export default moment.defineLocale('mk', { + months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'), + weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'), + weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'D.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd, D MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[Денес во] LT', + nextDay : '[Утре во] LT', + nextWeek : '[Во] dddd [во] LT', + lastDay : '[Вчера во] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + case 6: + return '[Изминатата] dddd [во] LT'; + case 1: + case 2: + case 4: + case 5: + return '[Изминатиот] dddd [во] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'после %s', + past : 'пред %s', + s : 'неколку секунди', + m : 'минута', + mm : '%d минути', + h : 'час', + hh : '%d часа', + d : 'ден', + dd : '%d дена', + M : 'месец', + MM : '%d месеци', + y : 'година', + yy : '%d години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + ordinal : function (number) { + var lastDigit = number % 10, + last2Digits = number % 100; + if (number === 0) { + return number + '-ев'; + } else if (last2Digits === 0) { + return number + '-ен'; + } else if (last2Digits > 10 && last2Digits < 20) { + return number + '-ти'; + } else if (lastDigit === 1) { + return number + '-ви'; + } else if (lastDigit === 2) { + return number + '-ри'; + } else if (lastDigit === 7 || lastDigit === 8) { + return number + '-ми'; + } else { + return number + '-ти'; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,72 @@
+//! moment.js locale configuration +//! locale : Malayalam [ml] +//! author : Floyd Pink : https://github.com/floydpink + +import moment from '../moment'; + +export default moment.defineLocale('ml', { + months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'), + monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'), + monthsParseExact : true, + weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'), + weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'), + weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'), + longDateFormat : { + LT : 'A h:mm -നു', + LTS : 'A h:mm:ss -നു', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm -നു', + LLLL : 'dddd, D MMMM YYYY, A h:mm -നു' + }, + calendar : { + sameDay : '[ഇന്ന്] LT', + nextDay : '[നാളെ] LT', + nextWeek : 'dddd, LT', + lastDay : '[ഇന്നലെ] LT', + lastWeek : '[കഴിഞ്ഞ] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s കഴിഞ്ഞ്', + past : '%s മുൻപ്', + s : 'അൽപ നിമിഷങ്ങൾ', + m : 'ഒരു മിനിറ്റ്', + mm : '%d മിനിറ്റ്', + h : 'ഒരു മണിക്കൂർ', + hh : '%d മണിക്കൂർ', + d : 'ഒരു ദിവസം', + dd : '%d ദിവസം', + M : 'ഒരു മാസം', + MM : '%d മാസം', + y : 'ഒരു വർഷം', + yy : '%d വർഷം' + }, + meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if ((meridiem === 'രാത്രി' && hour >= 4) || + meridiem === 'ഉച്ച കഴിഞ്ഞ്' || + meridiem === 'വൈകുന്നേരം') { + return hour + 12; + } else { + return hour; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'രാത്രി'; + } else if (hour < 12) { + return 'രാവിലെ'; + } else if (hour < 17) { + return 'ഉച്ച കഴിഞ്ഞ്'; + } else if (hour < 20) { + return 'വൈകുന്നേരം'; + } else { + return 'രാത്രി'; + } + } +}); +
@@ -0,0 +1,150 @@
+//! moment.js locale configuration +//! locale : Marathi [mr] +//! author : Harshad Kale : https://github.com/kalehv +//! author : Vivek Athalye : https://github.com/vnathalye + +import moment from '../moment'; + +var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' +}, +numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' +}; + +function relativeTimeMr(number, withoutSuffix, string, isFuture) +{ + var output = ''; + if (withoutSuffix) { + switch (string) { + case 's': output = 'काही सेकंद'; break; + case 'm': output = 'एक मिनिट'; break; + case 'mm': output = '%d मिनिटे'; break; + case 'h': output = 'एक तास'; break; + case 'hh': output = '%d तास'; break; + case 'd': output = 'एक दिवस'; break; + case 'dd': output = '%d दिवस'; break; + case 'M': output = 'एक महिना'; break; + case 'MM': output = '%d महिने'; break; + case 'y': output = 'एक वर्ष'; break; + case 'yy': output = '%d वर्षे'; break; + } + } + else { + switch (string) { + case 's': output = 'काही सेकंदां'; break; + case 'm': output = 'एका मिनिटा'; break; + case 'mm': output = '%d मिनिटां'; break; + case 'h': output = 'एका तासा'; break; + case 'hh': output = '%d तासां'; break; + case 'd': output = 'एका दिवसा'; break; + case 'dd': output = '%d दिवसां'; break; + case 'M': output = 'एका महिन्या'; break; + case 'MM': output = '%d महिन्यां'; break; + case 'y': output = 'एका वर्षा'; break; + case 'yy': output = '%d वर्षां'; break; + } + } + return output.replace(/%d/i, number); +} + +export default moment.defineLocale('mr', { + months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'), + monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'), + monthsParseExact : true, + weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm वाजता', + LTS : 'A h:mm:ss वाजता', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm वाजता', + LLLL : 'dddd, D MMMM YYYY, A h:mm वाजता' + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[उद्या] LT', + nextWeek : 'dddd, LT', + lastDay : '[काल] LT', + lastWeek: '[मागील] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future: '%sमध्ये', + past: '%sपूर्वी', + s: relativeTimeMr, + m: relativeTimeMr, + mm: relativeTimeMr, + h: relativeTimeMr, + hh: relativeTimeMr, + d: relativeTimeMr, + dd: relativeTimeMr, + M: relativeTimeMr, + MM: relativeTimeMr, + y: relativeTimeMr, + yy: relativeTimeMr + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + meridiemParse: /रात्री|सकाळी|दुपारी|सायंकाळी/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात्री') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सकाळी') { + return hour; + } else if (meridiem === 'दुपारी') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'सायंकाळी') { + return hour + 12; + } + }, + meridiem: function (hour, minute, isLower) { + if (hour < 4) { + return 'रात्री'; + } else if (hour < 10) { + return 'सकाळी'; + } else if (hour < 17) { + return 'दुपारी'; + } else if (hour < 20) { + return 'सायंकाळी'; + } else { + return 'रात्री'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,74 @@
+//! moment.js locale configuration +//! locale : Malay [ms-my] +//! note : DEPRECATED, the correct one is [ms] +//! author : Weldan Jamili : https://github.com/weldan + +import moment from '../moment'; + +export default moment.defineLocale('ms-my', { + months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'), + monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'), + weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'), + weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'), + weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /pagi|tengahari|petang|malam/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'tengahari') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'petang' || meridiem === 'malam') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'tengahari'; + } else if (hours < 19) { + return 'petang'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Esok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kelmarin pukul] LT', + lastWeek : 'dddd [lepas pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'dalam %s', + past : '%s yang lepas', + s : 'beberapa saat', + m : 'seminit', + mm : '%d minit', + h : 'sejam', + hh : '%d jam', + d : 'sehari', + dd : '%d hari', + M : 'sebulan', + MM : '%d bulan', + y : 'setahun', + yy : '%d tahun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,73 @@
+//! moment.js locale configuration +//! locale : Malay [ms] +//! author : Weldan Jamili : https://github.com/weldan + +import moment from '../moment'; + +export default moment.defineLocale('ms', { + months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'), + monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'), + weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'), + weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'), + weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] HH.mm', + LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' + }, + meridiemParse: /pagi|tengahari|petang|malam/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'tengahari') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'petang' || meridiem === 'malam') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'pagi'; + } else if (hours < 15) { + return 'tengahari'; + } else if (hours < 19) { + return 'petang'; + } else { + return 'malam'; + } + }, + calendar : { + sameDay : '[Hari ini pukul] LT', + nextDay : '[Esok pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kelmarin pukul] LT', + lastWeek : 'dddd [lepas pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'dalam %s', + past : '%s yang lepas', + s : 'beberapa saat', + m : 'seminit', + mm : '%d minit', + h : 'sejam', + hh : '%d jam', + d : 'sehari', + dd : '%d hari', + M : 'sebulan', + MM : '%d bulan', + y : 'setahun', + yy : '%d tahun' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,84 @@
+//! moment.js locale configuration +//! locale : Burmese [my] +//! author : Squar team, mysquar.com + +import moment from '../moment'; + +var symbolMap = { + '1': '၁', + '2': '၂', + '3': '၃', + '4': '၄', + '5': '၅', + '6': '၆', + '7': '၇', + '8': '၈', + '9': '၉', + '0': '၀' +}, numberMap = { + '၁': '1', + '၂': '2', + '၃': '3', + '၄': '4', + '၅': '5', + '၆': '6', + '၇': '7', + '၈': '8', + '၉': '9', + '၀': '0' +}; + +export default moment.defineLocale('my', { + months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'), + monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'), + weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'), + weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + + longDateFormat: { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY HH:mm', + LLLL: 'dddd D MMMM YYYY HH:mm' + }, + calendar: { + sameDay: '[ယနေ.] LT [မှာ]', + nextDay: '[မနက်ဖြန်] LT [မှာ]', + nextWeek: 'dddd LT [မှာ]', + lastDay: '[မနေ.က] LT [မှာ]', + lastWeek: '[ပြီးခဲ့သော] dddd LT [မှာ]', + sameElse: 'L' + }, + relativeTime: { + future: 'လာမည့် %s မှာ', + past: 'လွန်ခဲ့သော %s က', + s: 'စက္ကန်.အနည်းငယ်', + m: 'တစ်မိနစ်', + mm: '%d မိနစ်', + h: 'တစ်နာရီ', + hh: '%d နာရီ', + d: 'တစ်ရက်', + dd: '%d ရက်', + M: 'တစ်လ', + MM: '%d လ', + y: 'တစ်နှစ်', + yy: '%d နှစ်' + }, + preparse: function (string) { + return string.replace(/[၁၂၃၄၅၆၇၈၉၀]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,54 @@
+//! moment.js locale configuration +//! locale : Norwegian Bokmål [nb] +//! authors : Espen Hovlandsdal : https://github.com/rexxars +//! Sigurd Gartmann : https://github.com/sigurdga + +import moment from '../moment'; + +export default moment.defineLocale('nb', { + months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.'.split('_'), + monthsParseExact : true, + weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'), + weekdaysShort : 'sø._ma._ti._on._to._fr._lø.'.split('_'), + weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] HH:mm', + LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm' + }, + calendar : { + sameDay: '[i dag kl.] LT', + nextDay: '[i morgen kl.] LT', + nextWeek: 'dddd [kl.] LT', + lastDay: '[i går kl.] LT', + lastWeek: '[forrige] dddd [kl.] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : '%s siden', + s : 'noen sekunder', + m : 'ett minutt', + mm : '%d minutter', + h : 'en time', + hh : '%d timer', + d : 'en dag', + dd : '%d dager', + M : 'en måned', + MM : '%d måneder', + y : 'ett år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,114 @@
+//! moment.js locale configuration +//! locale : Nepalese [ne] +//! author : suvash : https://github.com/suvash + +import moment from '../moment'; + +var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' +}, +numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' +}; + +export default moment.defineLocale('ne', { + months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'), + monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'), + monthsParseExact : true, + weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'), + weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'), + weekdaysMin : 'आ._सो._मं._बु._बि._शु._श.'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'Aको h:mm बजे', + LTS : 'Aको h:mm:ss बजे', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, Aको h:mm बजे', + LLLL : 'dddd, D MMMM YYYY, Aको h:mm बजे' + }, + preparse: function (string) { + return string.replace(/[१२३४५६७८९०]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + meridiemParse: /राति|बिहान|दिउँसो|साँझ/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'राति') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'बिहान') { + return hour; + } else if (meridiem === 'दिउँसो') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'साँझ') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 3) { + return 'राति'; + } else if (hour < 12) { + return 'बिहान'; + } else if (hour < 16) { + return 'दिउँसो'; + } else if (hour < 20) { + return 'साँझ'; + } else { + return 'राति'; + } + }, + calendar : { + sameDay : '[आज] LT', + nextDay : '[भोलि] LT', + nextWeek : '[आउँदो] dddd[,] LT', + lastDay : '[हिजो] LT', + lastWeek : '[गएको] dddd[,] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%sमा', + past : '%s अगाडि', + s : 'केही क्षण', + m : 'एक मिनेट', + mm : '%d मिनेट', + h : 'एक घण्टा', + hh : '%d घण्टा', + d : 'एक दिन', + dd : '%d दिन', + M : 'एक महिना', + MM : '%d महिना', + y : 'एक बर्ष', + yy : '%d बर्ष' + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,64 @@
+//! moment.js locale configuration +//! locale : Dutch [nl] +//! author : Joris Röling : https://github.com/jjupiter + +import moment from '../moment'; + +var monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_'), + monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_'); + +export default moment.defineLocale('nl', { + months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShortWithoutDots[m.month()]; + } else { + return monthsShortWithDots[m.month()]; + } + }, + monthsParseExact : true, + weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'), + weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'), + weekdaysMin : 'Zo_Ma_Di_Wo_Do_Vr_Za'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[vandaag om] LT', + nextDay: '[morgen om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[gisteren om] LT', + lastWeek: '[afgelopen] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'over %s', + past : '%s geleden', + s : 'een paar seconden', + m : 'één minuut', + mm : '%d minuten', + h : 'één uur', + hh : '%d uur', + d : 'één dag', + dd : '%d dagen', + M : 'één maand', + MM : '%d maanden', + y : 'één jaar', + yy : '%d jaar' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,51 @@
+//! moment.js locale configuration +//! locale : Nynorsk [nn] +//! author : https://github.com/mechuwind + +import moment from '../moment'; + +export default moment.defineLocale('nn', { + months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), + weekdays : 'sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag'.split('_'), + weekdaysShort : 'sun_mån_tys_ons_tor_fre_lau'.split('_'), + weekdaysMin : 'su_må_ty_on_to_fr_lø'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] H:mm', + LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm' + }, + calendar : { + sameDay: '[I dag klokka] LT', + nextDay: '[I morgon klokka] LT', + nextWeek: 'dddd [klokka] LT', + lastDay: '[I går klokka] LT', + lastWeek: '[Føregåande] dddd [klokka] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : '%s sidan', + s : 'nokre sekund', + m : 'eit minutt', + mm : '%d minutt', + h : 'ein time', + hh : '%d timar', + d : 'ein dag', + dd : '%d dagar', + M : 'ein månad', + MM : '%d månader', + y : 'eit år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,115 @@
+//! moment.js locale configuration +//! locale : Punjabi (India) [pa-in] +//! author : Harpreet Singh : https://github.com/harpreetkhalsagtbit + +import moment from '../moment'; + +var symbolMap = { + '1': '੧', + '2': '੨', + '3': '੩', + '4': '੪', + '5': '੫', + '6': '੬', + '7': '੭', + '8': '੮', + '9': '੯', + '0': '੦' +}, +numberMap = { + '੧': '1', + '੨': '2', + '੩': '3', + '੪': '4', + '੫': '5', + '੬': '6', + '੭': '7', + '੮': '8', + '੯': '9', + '੦': '0' +}; + +export default moment.defineLocale('pa-in', { + // There are months name as per Nanakshahi Calender but they are not used as rigidly in modern Punjabi. + months : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'), + monthsShort : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'), + weekdays : 'ਐਤਵਾਰ_ਸੋਮਵਾਰ_ਮੰਗਲਵਾਰ_ਬੁਧਵਾਰ_ਵੀਰਵਾਰ_ਸ਼ੁੱਕਰਵਾਰ_ਸ਼ਨੀਚਰਵਾਰ'.split('_'), + weekdaysShort : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'), + weekdaysMin : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'), + longDateFormat : { + LT : 'A h:mm ਵਜੇ', + LTS : 'A h:mm:ss ਵਜੇ', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm ਵਜੇ', + LLLL : 'dddd, D MMMM YYYY, A h:mm ਵਜੇ' + }, + calendar : { + sameDay : '[ਅਜ] LT', + nextDay : '[ਕਲ] LT', + nextWeek : 'dddd, LT', + lastDay : '[ਕਲ] LT', + lastWeek : '[ਪਿਛਲੇ] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s ਵਿੱਚ', + past : '%s ਪਿਛਲੇ', + s : 'ਕੁਝ ਸਕਿੰਟ', + m : 'ਇਕ ਮਿੰਟ', + mm : '%d ਮਿੰਟ', + h : 'ਇੱਕ ਘੰਟਾ', + hh : '%d ਘੰਟੇ', + d : 'ਇੱਕ ਦਿਨ', + dd : '%d ਦਿਨ', + M : 'ਇੱਕ ਮਹੀਨਾ', + MM : '%d ਮਹੀਨੇ', + y : 'ਇੱਕ ਸਾਲ', + yy : '%d ਸਾਲ' + }, + preparse: function (string) { + return string.replace(/[੧੨੩੪੫੬੭੮੯੦]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + // Punjabi notation for meridiems are quite fuzzy in practice. While there exists + // a rigid notion of a 'Pahar' it is not used as rigidly in modern Punjabi. + meridiemParse: /ਰਾਤ|ਸਵੇਰ|ਦੁਪਹਿਰ|ਸ਼ਾਮ/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'ਰਾਤ') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'ਸਵੇਰ') { + return hour; + } else if (meridiem === 'ਦੁਪਹਿਰ') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'ਸ਼ਾਮ') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ਰਾਤ'; + } else if (hour < 10) { + return 'ਸਵੇਰ'; + } else if (hour < 17) { + return 'ਦੁਪਹਿਰ'; + } else if (hour < 20) { + return 'ਸ਼ਾਮ'; + } else { + return 'ਰਾਤ'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,95 @@
+//! moment.js locale configuration +//! locale : Polish [pl] +//! author : Rafal Hirsz : https://github.com/evoL + +import moment from '../moment'; + +var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split('_'), + monthsSubjective = 'stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia'.split('_'); +function plural(n) { + return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1); +} +function translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'minuta' : 'minutę'; + case 'mm': + return result + (plural(number) ? 'minuty' : 'minut'); + case 'h': + return withoutSuffix ? 'godzina' : 'godzinę'; + case 'hh': + return result + (plural(number) ? 'godziny' : 'godzin'); + case 'MM': + return result + (plural(number) ? 'miesiące' : 'miesięcy'); + case 'yy': + return result + (plural(number) ? 'lata' : 'lat'); + } +} + +export default moment.defineLocale('pl', { + months : function (momentToFormat, format) { + if (format === '') { + // Hack: if format empty we know this is used to generate + // RegExp by moment. Give then back both valid forms of months + // in RegExp ready format. + return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')'; + } else if (/D MMMM/.test(format)) { + return monthsSubjective[momentToFormat.month()]; + } else { + return monthsNominative[momentToFormat.month()]; + } + }, + monthsShort : 'sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru'.split('_'), + weekdays : 'niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota'.split('_'), + weekdaysShort : 'nie_pon_wt_śr_czw_pt_sb'.split('_'), + weekdaysMin : 'Nd_Pn_Wt_Śr_Cz_Pt_So'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Dziś o] LT', + nextDay: '[Jutro o] LT', + nextWeek: '[W] dddd [o] LT', + lastDay: '[Wczoraj o] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[W zeszłą niedzielę o] LT'; + case 3: + return '[W zeszłą środę o] LT'; + case 6: + return '[W zeszłą sobotę o] LT'; + default: + return '[W zeszły] dddd [o] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'za %s', + past : '%s temu', + s : 'kilka sekund', + m : translate, + mm : translate, + h : translate, + hh : translate, + d : '1 dzień', + dd : '%d dni', + M : 'miesiąc', + MM : translate, + y : 'rok', + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +});
@@ -0,0 +1,52 @@
+//! moment.js locale configuration +//! locale : Portuguese (Brazil) [pt-br] +//! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira + +import moment from '../moment'; + +export default moment.defineLocale('pt-br', { + months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'), + monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'), + weekdays : 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split('_'), + weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'), + weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY [às] HH:mm', + LLLL : 'dddd, D [de] MMMM [de] YYYY [às] HH:mm' + }, + calendar : { + sameDay: '[Hoje às] LT', + nextDay: '[Amanhã às] LT', + nextWeek: 'dddd [às] LT', + lastDay: '[Ontem às] LT', + lastWeek: function () { + return (this.day() === 0 || this.day() === 6) ? + '[Último] dddd [às] LT' : // Saturday + Sunday + '[Última] dddd [às] LT'; // Monday - Friday + }, + sameElse: 'L' + }, + relativeTime : { + future : 'em %s', + past : '%s atrás', + s : 'poucos segundos', + m : 'um minuto', + mm : '%d minutos', + h : 'uma hora', + hh : '%d horas', + d : 'um dia', + dd : '%d dias', + M : 'um mês', + MM : '%d meses', + y : 'um ano', + yy : '%d anos' + }, + ordinalParse: /\d{1,2}º/, + ordinal : '%dº' +}); +
@@ -0,0 +1,56 @@
+//! moment.js locale configuration +//! locale : Portuguese [pt] +//! author : Jefferson : https://github.com/jalex79 + +import moment from '../moment'; + +export default moment.defineLocale('pt', { + months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'), + monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'), + weekdays : 'Domingo_Segunda-Feira_Terça-Feira_Quarta-Feira_Quinta-Feira_Sexta-Feira_Sábado'.split('_'), + weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'), + weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY HH:mm', + LLLL : 'dddd, D [de] MMMM [de] YYYY HH:mm' + }, + calendar : { + sameDay: '[Hoje às] LT', + nextDay: '[Amanhã às] LT', + nextWeek: 'dddd [às] LT', + lastDay: '[Ontem às] LT', + lastWeek: function () { + return (this.day() === 0 || this.day() === 6) ? + '[Último] dddd [às] LT' : // Saturday + Sunday + '[Última] dddd [às] LT'; // Monday - Friday + }, + sameElse: 'L' + }, + relativeTime : { + future : 'em %s', + past : 'há %s', + s : 'segundos', + m : 'um minuto', + mm : '%d minutos', + h : 'uma hora', + hh : '%d horas', + d : 'um dia', + dd : '%d dias', + M : 'um mês', + MM : '%d meses', + y : 'um ano', + yy : '%d anos' + }, + ordinalParse: /\d{1,2}º/, + ordinal : '%dº', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,66 @@
+//! moment.js locale configuration +//! locale : Romanian [ro] +//! author : Vlad Gurdiga : https://github.com/gurdiga +//! author : Valentin Agachi : https://github.com/avaly + +import moment from '../moment'; + +function relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': 'minute', + 'hh': 'ore', + 'dd': 'zile', + 'MM': 'luni', + 'yy': 'ani' + }, + separator = ' '; + if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) { + separator = ' de '; + } + return number + separator + format[key]; +} + +export default moment.defineLocale('ro', { + months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'), + monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays : 'duminică_luni_marți_miercuri_joi_vineri_sâmbătă'.split('_'), + weekdaysShort : 'Dum_Lun_Mar_Mie_Joi_Vin_Sâm'.split('_'), + weekdaysMin : 'Du_Lu_Ma_Mi_Jo_Vi_Sâ'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY H:mm', + LLLL : 'dddd, D MMMM YYYY H:mm' + }, + calendar : { + sameDay: '[azi la] LT', + nextDay: '[mâine la] LT', + nextWeek: 'dddd [la] LT', + lastDay: '[ieri la] LT', + lastWeek: '[fosta] dddd [la] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'peste %s', + past : '%s în urmă', + s : 'câteva secunde', + m : 'un minut', + mm : relativeTimeWithPlural, + h : 'o oră', + hh : relativeTimeWithPlural, + d : 'o zi', + dd : relativeTimeWithPlural, + M : 'o lună', + MM : relativeTimeWithPlural, + y : 'un an', + yy : relativeTimeWithPlural + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,173 @@
+//! moment.js locale configuration +//! locale : Russian [ru] +//! author : Viktorminator : https://github.com/Viktorminator +//! Author : Menelion Elensúle : https://github.com/Oire +//! author : Коренберг Марк : https://github.com/socketpair + +import moment from '../moment'; + +function plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); +} +function relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут', + 'hh': 'час_часа_часов', + 'dd': 'день_дня_дней', + 'MM': 'месяц_месяца_месяцев', + 'yy': 'год_года_лет' + }; + if (key === 'm') { + return withoutSuffix ? 'минута' : 'минуту'; + } + else { + return number + ' ' + plural(format[key], +number); + } +} +var monthsParse = [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[йя]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i]; + +// http://new.gramota.ru/spravka/rules/139-prop : § 103 +// Сокращения месяцев: http://new.gramota.ru/spravka/buro/search-answer?s=242637 +// CLDR data: http://www.unicode.org/cldr/charts/28/summary/ru.html#1753 +export default moment.defineLocale('ru', { + months : { + format: 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_'), + standalone: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_') + }, + monthsShort : { + // по CLDR именно "июл." и "июн.", но какой смысл менять букву на точку ? + format: 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split('_'), + standalone: 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split('_') + }, + weekdays : { + standalone: 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'), + format: 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_'), + isFormat: /\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/ + }, + weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + monthsParse : monthsParse, + longMonthsParse : monthsParse, + shortMonthsParse : monthsParse, + + // полные названия с падежами, по три буквы, для некоторых, по 4 буквы, сокращения с точкой и без точки + monthsRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i, + + // копия предыдущего + monthsShortRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i, + + // полные названия с падежами + monthsStrictRegex: /^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i, + + // Выражение, которое соотвествует только сокращённым формам + monthsShortStrictRegex: /^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY г.', + LLL : 'D MMMM YYYY г., HH:mm', + LLLL : 'dddd, D MMMM YYYY г., HH:mm' + }, + calendar : { + sameDay: '[Сегодня в] LT', + nextDay: '[Завтра в] LT', + lastDay: '[Вчера в] LT', + nextWeek: function (now) { + if (now.week() !== this.week()) { + switch (this.day()) { + case 0: + return '[В следующее] dddd [в] LT'; + case 1: + case 2: + case 4: + return '[В следующий] dddd [в] LT'; + case 3: + case 5: + case 6: + return '[В следующую] dddd [в] LT'; + } + } else { + if (this.day() === 2) { + return '[Во] dddd [в] LT'; + } else { + return '[В] dddd [в] LT'; + } + } + }, + lastWeek: function (now) { + if (now.week() !== this.week()) { + switch (this.day()) { + case 0: + return '[В прошлое] dddd [в] LT'; + case 1: + case 2: + case 4: + return '[В прошлый] dddd [в] LT'; + case 3: + case 5: + case 6: + return '[В прошлую] dddd [в] LT'; + } + } else { + if (this.day() === 2) { + return '[Во] dddd [в] LT'; + } else { + return '[В] dddd [в] LT'; + } + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'через %s', + past : '%s назад', + s : 'несколько секунд', + m : relativeTimeWithPlural, + mm : relativeTimeWithPlural, + h : 'час', + hh : relativeTimeWithPlural, + d : 'день', + dd : relativeTimeWithPlural, + M : 'месяц', + MM : relativeTimeWithPlural, + y : 'год', + yy : relativeTimeWithPlural + }, + meridiemParse: /ночи|утра|дня|вечера/i, + isPM : function (input) { + return /^(дня|вечера)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночи'; + } else if (hour < 12) { + return 'утра'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечера'; + } + }, + ordinalParse: /\d{1,2}-(й|го|я)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + return number + '-й'; + case 'D': + return number + '-го'; + case 'w': + case 'W': + return number + '-я'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +});
@@ -0,0 +1,51 @@
+//! moment.js locale configuration +//! locale : Northern Sami [se] +//! authors : Bård Rolstad Henriksen : https://github.com/karamell + + +import moment from '../moment'; + +export default moment.defineLocale('se', { + months : 'ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu'.split('_'), + monthsShort : 'ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov'.split('_'), + weekdays : 'sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat'.split('_'), + weekdaysShort : 'sotn_vuos_maŋ_gask_duor_bear_láv'.split('_'), + weekdaysMin : 's_v_m_g_d_b_L'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'MMMM D. [b.] YYYY', + LLL : 'MMMM D. [b.] YYYY [ti.] HH:mm', + LLLL : 'dddd, MMMM D. [b.] YYYY [ti.] HH:mm' + }, + calendar : { + sameDay: '[otne ti] LT', + nextDay: '[ihttin ti] LT', + nextWeek: 'dddd [ti] LT', + lastDay: '[ikte ti] LT', + lastWeek: '[ovddit] dddd [ti] LT', + sameElse: 'L' + }, + relativeTime : { + future : '%s geažes', + past : 'maŋit %s', + s : 'moadde sekunddat', + m : 'okta minuhta', + mm : '%d minuhtat', + h : 'okta diimmu', + hh : '%d diimmut', + d : 'okta beaivi', + dd : '%d beaivvit', + M : 'okta mánnu', + MM : '%d mánut', + y : 'okta jahki', + yy : '%d jagit' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +});
@@ -0,0 +1,61 @@
+//! moment.js locale configuration +//! locale : Sinhalese [si] +//! author : Sampath Sitinamaluwa : https://github.com/sampathsris + +import moment from '../moment'; + +/*jshint -W100*/ +export default moment.defineLocale('si', { + months : 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split('_'), + monthsShort : 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split('_'), + weekdays : 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split('_'), + weekdaysShort : 'ඉරි_සඳු_අඟ_බදා_බ්රහ_සිකු_සෙන'.split('_'), + weekdaysMin : 'ඉ_ස_අ_බ_බ්ර_සි_සෙ'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'a h:mm', + LTS : 'a h:mm:ss', + L : 'YYYY/MM/DD', + LL : 'YYYY MMMM D', + LLL : 'YYYY MMMM D, a h:mm', + LLLL : 'YYYY MMMM D [වැනි] dddd, a h:mm:ss' + }, + calendar : { + sameDay : '[අද] LT[ට]', + nextDay : '[හෙට] LT[ට]', + nextWeek : 'dddd LT[ට]', + lastDay : '[ඊයේ] LT[ට]', + lastWeek : '[පසුගිය] dddd LT[ට]', + sameElse : 'L' + }, + relativeTime : { + future : '%sකින්', + past : '%sකට පෙර', + s : 'තත්පර කිහිපය', + m : 'මිනිත්තුව', + mm : 'මිනිත්තු %d', + h : 'පැය', + hh : 'පැය %d', + d : 'දිනය', + dd : 'දින %d', + M : 'මාසය', + MM : 'මාස %d', + y : 'වසර', + yy : 'වසර %d' + }, + ordinalParse: /\d{1,2} වැනි/, + ordinal : function (number) { + return number + ' වැනි'; + }, + meridiemParse : /පෙර වරු|පස් වරු|පෙ.ව|ප.ව./, + isPM : function (input) { + return input === 'ප.ව.' || input === 'පස් වරු'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'ප.ව.' : 'පස් වරු'; + } else { + return isLower ? 'පෙ.ව.' : 'පෙර වරු'; + } + } +});
@@ -0,0 +1,141 @@
+//! moment.js locale configuration +//! locale : Slovak [sk] +//! author : Martin Minka : https://github.com/k2s +//! based on work of petrbela : https://github.com/petrbela + +import moment from '../moment'; + +var months = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_'), + monthsShort = 'jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec'.split('_'); +function plural(n) { + return (n > 1) && (n < 5); +} +function translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': // a few seconds / in a few seconds / a few seconds ago + return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami'; + case 'm': // a minute / in a minute / a minute ago + return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou'); + case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'minúty' : 'minút'); + } else { + return result + 'minútami'; + } + break; + case 'h': // an hour / in an hour / an hour ago + return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou'); + case 'hh': // 9 hours / in 9 hours / 9 hours ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'hodiny' : 'hodín'); + } else { + return result + 'hodinami'; + } + break; + case 'd': // a day / in a day / a day ago + return (withoutSuffix || isFuture) ? 'deň' : 'dňom'; + case 'dd': // 9 days / in 9 days / 9 days ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'dni' : 'dní'); + } else { + return result + 'dňami'; + } + break; + case 'M': // a month / in a month / a month ago + return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom'; + case 'MM': // 9 months / in 9 months / 9 months ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'mesiace' : 'mesiacov'); + } else { + return result + 'mesiacmi'; + } + break; + case 'y': // a year / in a year / a year ago + return (withoutSuffix || isFuture) ? 'rok' : 'rokom'; + case 'yy': // 9 years / in 9 years / 9 years ago + if (withoutSuffix || isFuture) { + return result + (plural(number) ? 'roky' : 'rokov'); + } else { + return result + 'rokmi'; + } + break; + } +} + +export default moment.defineLocale('sk', { + months : months, + monthsShort : monthsShort, + weekdays : 'nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota'.split('_'), + weekdaysShort : 'ne_po_ut_st_št_pi_so'.split('_'), + weekdaysMin : 'ne_po_ut_st_št_pi_so'.split('_'), + longDateFormat : { + LT: 'H:mm', + LTS : 'H:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd D. MMMM YYYY H:mm' + }, + calendar : { + sameDay: '[dnes o] LT', + nextDay: '[zajtra o] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[v nedeľu o] LT'; + case 1: + case 2: + return '[v] dddd [o] LT'; + case 3: + return '[v stredu o] LT'; + case 4: + return '[vo štvrtok o] LT'; + case 5: + return '[v piatok o] LT'; + case 6: + return '[v sobotu o] LT'; + } + }, + lastDay: '[včera o] LT', + lastWeek: function () { + switch (this.day()) { + case 0: + return '[minulú nedeľu o] LT'; + case 1: + case 2: + return '[minulý] dddd [o] LT'; + case 3: + return '[minulú stredu o] LT'; + case 4: + case 5: + return '[minulý] dddd [o] LT'; + case 6: + return '[minulú sobotu o] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'za %s', + past : 'pred %s', + s : translate, + m : translate, + mm : translate, + h : translate, + hh : translate, + d : translate, + dd : translate, + M : translate, + MM : translate, + y : translate, + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,152 @@
+//! moment.js locale configuration +//! locale : Slovenian [sl] +//! author : Robert Sedovšek : https://github.com/sedovsek + +import moment from '../moment'; + +function processRelativeTime(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nekaj sekund' : 'nekaj sekundami'; + case 'm': + return withoutSuffix ? 'ena minuta' : 'eno minuto'; + case 'mm': + if (number === 1) { + result += withoutSuffix ? 'minuta' : 'minuto'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'minuti' : 'minutama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'minute' : 'minutami'; + } else { + result += withoutSuffix || isFuture ? 'minut' : 'minutami'; + } + return result; + case 'h': + return withoutSuffix ? 'ena ura' : 'eno uro'; + case 'hh': + if (number === 1) { + result += withoutSuffix ? 'ura' : 'uro'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'uri' : 'urama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'ure' : 'urami'; + } else { + result += withoutSuffix || isFuture ? 'ur' : 'urami'; + } + return result; + case 'd': + return withoutSuffix || isFuture ? 'en dan' : 'enim dnem'; + case 'dd': + if (number === 1) { + result += withoutSuffix || isFuture ? 'dan' : 'dnem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'dni' : 'dnevoma'; + } else { + result += withoutSuffix || isFuture ? 'dni' : 'dnevi'; + } + return result; + case 'M': + return withoutSuffix || isFuture ? 'en mesec' : 'enim mesecem'; + case 'MM': + if (number === 1) { + result += withoutSuffix || isFuture ? 'mesec' : 'mesecem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'meseca' : 'mesecema'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'mesece' : 'meseci'; + } else { + result += withoutSuffix || isFuture ? 'mesecev' : 'meseci'; + } + return result; + case 'y': + return withoutSuffix || isFuture ? 'eno leto' : 'enim letom'; + case 'yy': + if (number === 1) { + result += withoutSuffix || isFuture ? 'leto' : 'letom'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'leti' : 'letoma'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'leta' : 'leti'; + } else { + result += withoutSuffix || isFuture ? 'let' : 'leti'; + } + return result; + } +} + +export default moment.defineLocale('sl', { + months : 'januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december'.split('_'), + monthsShort : 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays : 'nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota'.split('_'), + weekdaysShort : 'ned._pon._tor._sre._čet._pet._sob.'.split('_'), + weekdaysMin : 'ne_po_to_sr_če_pe_so'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H:mm', + LTS : 'H:mm:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY H:mm', + LLLL : 'dddd, D. MMMM YYYY H:mm' + }, + calendar : { + sameDay : '[danes ob] LT', + nextDay : '[jutri ob] LT', + + nextWeek : function () { + switch (this.day()) { + case 0: + return '[v] [nedeljo] [ob] LT'; + case 3: + return '[v] [sredo] [ob] LT'; + case 6: + return '[v] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[v] dddd [ob] LT'; + } + }, + lastDay : '[včeraj ob] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + return '[prejšnjo] [nedeljo] [ob] LT'; + case 3: + return '[prejšnjo] [sredo] [ob] LT'; + case 6: + return '[prejšnjo] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prejšnji] dddd [ob] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'čez %s', + past : 'pred %s', + s : processRelativeTime, + m : processRelativeTime, + mm : processRelativeTime, + h : processRelativeTime, + hh : processRelativeTime, + d : processRelativeTime, + dd : processRelativeTime, + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +});
@@ -0,0 +1,61 @@
+//! moment.js locale configuration +//! locale : Albanian [sq] +//! author : Flakërim Ismani : https://github.com/flakerimi +//! author: Menelion Elensúle: https://github.com/Oire (tests) +//! author : Oerd Cukalla : https://github.com/oerd (fixes) + +import moment from '../moment'; + +export default moment.defineLocale('sq', { + months : 'Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor'.split('_'), + monthsShort : 'Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj'.split('_'), + weekdays : 'E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë'.split('_'), + weekdaysShort : 'Die_Hën_Mar_Mër_Enj_Pre_Sht'.split('_'), + weekdaysMin : 'D_H_Ma_Më_E_P_Sh'.split('_'), + weekdaysParseExact : true, + meridiemParse: /PD|MD/, + isPM: function (input) { + return input.charAt(0) === 'M'; + }, + meridiem : function (hours, minutes, isLower) { + return hours < 12 ? 'PD' : 'MD'; + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[Sot në] LT', + nextDay : '[Nesër në] LT', + nextWeek : 'dddd [në] LT', + lastDay : '[Dje në] LT', + lastWeek : 'dddd [e kaluar në] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'në %s', + past : '%s më parë', + s : 'disa sekonda', + m : 'një minutë', + mm : '%d minuta', + h : 'një orë', + hh : '%d orë', + d : 'një ditë', + dd : '%d ditë', + M : 'një muaj', + MM : '%d muaj', + y : 'një vit', + yy : '%d vite' + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,101 @@
+//! moment.js locale configuration +//! locale : Serbian Cyrillic [sr-cyrl] +//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j + +import moment from '../moment'; + +var translator = { + words: { //Different grammatical cases + m: ['један минут', 'једне минуте'], + mm: ['минут', 'минуте', 'минута'], + h: ['један сат', 'једног сата'], + hh: ['сат', 'сата', 'сати'], + dd: ['дан', 'дана', 'дана'], + MM: ['месец', 'месеца', 'месеци'], + yy: ['година', 'године', 'година'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + translator.correctGrammaticalCase(number, wordKey); + } + } +}; + +export default moment.defineLocale('sr-cyrl', { + months: 'јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар'.split('_'), + monthsShort: 'јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.'.split('_'), + monthsParseExact: true, + weekdays: 'недеља_понедељак_уторак_среда_четвртак_петак_субота'.split('_'), + weekdaysShort: 'нед._пон._уто._сре._чет._пет._суб.'.split('_'), + weekdaysMin: 'не_по_ут_ср_че_пе_су'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm', + LTS : 'H:mm:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm', + LLLL: 'dddd, D. MMMM YYYY H:mm' + }, + calendar: { + sameDay: '[данас у] LT', + nextDay: '[сутра у] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[у] [недељу] [у] LT'; + case 3: + return '[у] [среду] [у] LT'; + case 6: + return '[у] [суботу] [у] LT'; + case 1: + case 2: + case 4: + case 5: + return '[у] dddd [у] LT'; + } + }, + lastDay : '[јуче у] LT', + lastWeek : function () { + var lastWeekDays = [ + '[прошле] [недеље] [у] LT', + '[прошлог] [понедељка] [у] LT', + '[прошлог] [уторка] [у] LT', + '[прошле] [среде] [у] LT', + '[прошлог] [четвртка] [у] LT', + '[прошлог] [петка] [у] LT', + '[прошле] [суботе] [у] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'за %s', + past : 'пре %s', + s : 'неколико секунди', + m : translator.translate, + mm : translator.translate, + h : translator.translate, + hh : translator.translate, + d : 'дан', + dd : translator.translate, + M : 'месец', + MM : translator.translate, + y : 'годину', + yy : translator.translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,101 @@
+//! moment.js locale configuration +//! locale : Serbian [sr] +//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j + +import moment from '../moment'; + +var translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jedne minute'], + mm: ['minut', 'minute', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mesec', 'meseca', 'meseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + translator.correctGrammaticalCase(number, wordKey); + } + } +}; + +export default moment.defineLocale('sr', { + months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'), + monthsParseExact: true, + weekdays: 'nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota'.split('_'), + weekdaysShort: 'ned._pon._uto._sre._čet._pet._sub.'.split('_'), + weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'), + weekdaysParseExact : true, + longDateFormat: { + LT: 'H:mm', + LTS : 'H:mm:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY H:mm', + LLLL: 'dddd, D. MMMM YYYY H:mm' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sutra u] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedelju] [u] LT'; + case 3: + return '[u] [sredu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedelje] [u] LT', + '[prošlog] [ponedeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'pre %s', + s : 'nekoliko sekundi', + m : translator.translate, + mm : translator.translate, + h : translator.translate, + hh : translator.translate, + d : 'dan', + dd : translator.translate, + M : 'mesec', + MM : translator.translate, + y : 'godinu', + yy : translator.translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,80 @@
+//! moment.js locale configuration +//! locale : Swazi [ss] +//! author : Nicolai Davies<mail@nicolai.io> : https://github.com/nicolaidavies + + +import moment from '../moment'; + +export default moment.defineLocale('ss', { + months : "Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split('_'), + monthsShort : 'Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo'.split('_'), + weekdays : 'Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo'.split('_'), + weekdaysShort : 'Lis_Umb_Lsb_Les_Lsi_Lsh_Umg'.split('_'), + weekdaysMin : 'Li_Us_Lb_Lt_Ls_Lh_Ug'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss A', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY h:mm A', + LLLL : 'dddd, D MMMM YYYY h:mm A' + }, + calendar : { + sameDay : '[Namuhla nga] LT', + nextDay : '[Kusasa nga] LT', + nextWeek : 'dddd [nga] LT', + lastDay : '[Itolo nga] LT', + lastWeek : 'dddd [leliphelile] [nga] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'nga %s', + past : 'wenteka nga %s', + s : 'emizuzwana lomcane', + m : 'umzuzu', + mm : '%d emizuzu', + h : 'lihora', + hh : '%d emahora', + d : 'lilanga', + dd : '%d emalanga', + M : 'inyanga', + MM : '%d tinyanga', + y : 'umnyaka', + yy : '%d iminyaka' + }, + meridiemParse: /ekuseni|emini|entsambama|ebusuku/, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'ekuseni'; + } else if (hours < 15) { + return 'emini'; + } else if (hours < 19) { + return 'entsambama'; + } else { + return 'ebusuku'; + } + }, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'ekuseni') { + return hour; + } else if (meridiem === 'emini') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'entsambama' || meridiem === 'ebusuku') { + if (hour === 0) { + return 0; + } + return hour + 12; + } + }, + ordinalParse: /\d{1,2}/, + ordinal : '%d', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,60 @@
+//! moment.js locale configuration +//! locale : Swedish [sv] +//! author : Jens Alm : https://github.com/ulmus + +import moment from '../moment'; + +export default moment.defineLocale('sv', { + months : 'januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december'.split('_'), + monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'), + weekdays : 'söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag'.split('_'), + weekdaysShort : 'sön_mån_tis_ons_tor_fre_lör'.split('_'), + weekdaysMin : 'sö_må_ti_on_to_fr_lö'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'YYYY-MM-DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [kl.] HH:mm', + LLLL : 'dddd D MMMM YYYY [kl.] HH:mm', + lll : 'D MMM YYYY HH:mm', + llll : 'ddd D MMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Idag] LT', + nextDay: '[Imorgon] LT', + lastDay: '[Igår] LT', + nextWeek: '[På] dddd LT', + lastWeek: '[I] dddd[s] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : 'för %s sedan', + s : 'några sekunder', + m : 'en minut', + mm : '%d minuter', + h : 'en timme', + hh : '%d timmar', + d : 'en dag', + dd : '%d dagar', + M : 'en månad', + MM : '%d månader', + y : 'ett år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}(e|a)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'e' : + (b === 1) ? 'a' : + (b === 2) ? 'a' : + (b === 3) ? 'e' : 'e'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,50 @@
+//! moment.js locale configuration +//! locale : Swahili [sw] +//! author : Fahad Kassim : https://github.com/fadsel + +import moment from '../moment'; + +export default moment.defineLocale('sw', { + months : 'Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba'.split('_'), + monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi'.split('_'), + weekdaysShort : 'Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos'.split('_'), + weekdaysMin : 'J2_J3_J4_J5_Al_Ij_J1'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[leo saa] LT', + nextDay : '[kesho saa] LT', + nextWeek : '[wiki ijayo] dddd [saat] LT', + lastDay : '[jana] LT', + lastWeek : '[wiki iliyopita] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s baadaye', + past : 'tokea %s', + s : 'hivi punde', + m : 'dakika moja', + mm : 'dakika %d', + h : 'saa limoja', + hh : 'masaa %d', + d : 'siku moja', + dd : 'masiku %d', + M : 'mwezi mmoja', + MM : 'miezi %d', + y : 'mwaka mmoja', + yy : 'miaka %d' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,120 @@
+//! moment.js locale configuration +//! locale : Tamil [ta] +//! author : Arjunkumar Krishnamoorthy : https://github.com/tk120404 + +import moment from '../moment'; + +var symbolMap = { + '1': '௧', + '2': '௨', + '3': '௩', + '4': '௪', + '5': '௫', + '6': '௬', + '7': '௭', + '8': '௮', + '9': '௯', + '0': '௦' +}, numberMap = { + '௧': '1', + '௨': '2', + '௩': '3', + '௪': '4', + '௫': '5', + '௬': '6', + '௭': '7', + '௮': '8', + '௯': '9', + '௦': '0' +}; + +export default moment.defineLocale('ta', { + months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'), + weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'), + weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, HH:mm', + LLLL : 'dddd, D MMMM YYYY, HH:mm' + }, + calendar : { + sameDay : '[இன்று] LT', + nextDay : '[நாளை] LT', + nextWeek : 'dddd, LT', + lastDay : '[நேற்று] LT', + lastWeek : '[கடந்த வாரம்] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s இல்', + past : '%s முன்', + s : 'ஒரு சில விநாடிகள்', + m : 'ஒரு நிமிடம்', + mm : '%d நிமிடங்கள்', + h : 'ஒரு மணி நேரம்', + hh : '%d மணி நேரம்', + d : 'ஒரு நாள்', + dd : '%d நாட்கள்', + M : 'ஒரு மாதம்', + MM : '%d மாதங்கள்', + y : 'ஒரு வருடம்', + yy : '%d ஆண்டுகள்' + }, + ordinalParse: /\d{1,2}வது/, + ordinal : function (number) { + return number + 'வது'; + }, + preparse: function (string) { + return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) { + return numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }); + }, + // refer http://ta.wikipedia.org/s/1er1 + meridiemParse: /யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/, + meridiem : function (hour, minute, isLower) { + if (hour < 2) { + return ' யாமம்'; + } else if (hour < 6) { + return ' வைகறை'; // வைகறை + } else if (hour < 10) { + return ' காலை'; // காலை + } else if (hour < 14) { + return ' நண்பகல்'; // நண்பகல் + } else if (hour < 18) { + return ' எற்பாடு'; // எற்பாடு + } else if (hour < 22) { + return ' மாலை'; // மாலை + } else { + return ' யாமம்'; + } + }, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'யாமம்') { + return hour < 2 ? hour : hour + 12; + } else if (meridiem === 'வைகறை' || meridiem === 'காலை') { + return hour; + } else if (meridiem === 'நண்பகல்') { + return hour >= 10 ? hour : hour + 12; + } else { + return hour + 12; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,79 @@
+//! moment.js locale configuration +//! locale : Telugu [te] +//! author : Krishna Chaitanya Thota : https://github.com/kcthota + +import moment from '../moment'; + +export default moment.defineLocale('te', { + months : 'జనవరి_ఫిబ్రవరి_మార్చి_ఏప్రిల్_మే_జూన్_జూలై_ఆగస్టు_సెప్టెంబర్_అక్టోబర్_నవంబర్_డిసెంబర్'.split('_'), + monthsShort : 'జన._ఫిబ్ర._మార్చి_ఏప్రి._మే_జూన్_జూలై_ఆగ._సెప్._అక్టో._నవ._డిసె.'.split('_'), + monthsParseExact : true, + weekdays : 'ఆదివారం_సోమవారం_మంగళవారం_బుధవారం_గురువారం_శుక్రవారం_శనివారం'.split('_'), + weekdaysShort : 'ఆది_సోమ_మంగళ_బుధ_గురు_శుక్ర_శని'.split('_'), + weekdaysMin : 'ఆ_సో_మం_బు_గు_శు_శ'.split('_'), + longDateFormat : { + LT : 'A h:mm', + LTS : 'A h:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY, A h:mm', + LLLL : 'dddd, D MMMM YYYY, A h:mm' + }, + calendar : { + sameDay : '[నేడు] LT', + nextDay : '[రేపు] LT', + nextWeek : 'dddd, LT', + lastDay : '[నిన్న] LT', + lastWeek : '[గత] dddd, LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s లో', + past : '%s క్రితం', + s : 'కొన్ని క్షణాలు', + m : 'ఒక నిమిషం', + mm : '%d నిమిషాలు', + h : 'ఒక గంట', + hh : '%d గంటలు', + d : 'ఒక రోజు', + dd : '%d రోజులు', + M : 'ఒక నెల', + MM : '%d నెలలు', + y : 'ఒక సంవత్సరం', + yy : '%d సంవత్సరాలు' + }, + ordinalParse : /\d{1,2}వ/, + ordinal : '%dవ', + meridiemParse: /రాత్రి|ఉదయం|మధ్యాహ్నం|సాయంత్రం/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'రాత్రి') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'ఉదయం') { + return hour; + } else if (meridiem === 'మధ్యాహ్నం') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'సాయంత్రం') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'రాత్రి'; + } else if (hour < 10) { + return 'ఉదయం'; + } else if (hour < 17) { + return 'మధ్యాహ్నం'; + } else if (hour < 20) { + return 'సాయంత్రం'; + } else { + return 'రాత్రి'; + } + }, + week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + } +});
@@ -0,0 +1,57 @@
+//! moment.js locale configuration +//! locale : Thai [th] +//! author : Kridsada Thanabulpong : https://github.com/sirn + +import moment from '../moment'; + +export default moment.defineLocale('th', { + months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'), + monthsShort : 'ม.ค._ก.พ._มี.ค._เม.ย._พ.ค._มิ.ย._ก.ค._ส.ค._ก.ย._ต.ค._พ.ย._ธ.ค.'.split('_'), + monthsParseExact: true, + weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'), + weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference + weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'H นาฬิกา m นาที', + LTS : 'H นาฬิกา m นาที s วินาที', + L : 'YYYY/MM/DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY เวลา H นาฬิกา m นาที', + LLLL : 'วันddddที่ D MMMM YYYY เวลา H นาฬิกา m นาที' + }, + meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/, + isPM: function (input) { + return input === 'หลังเที่ยง'; + }, + meridiem : function (hour, minute, isLower) { + if (hour < 12) { + return 'ก่อนเที่ยง'; + } else { + return 'หลังเที่ยง'; + } + }, + calendar : { + sameDay : '[วันนี้ เวลา] LT', + nextDay : '[พรุ่งนี้ เวลา] LT', + nextWeek : 'dddd[หน้า เวลา] LT', + lastDay : '[เมื่อวานนี้ เวลา] LT', + lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'อีก %s', + past : '%sที่แล้ว', + s : 'ไม่กี่วินาที', + m : '1 นาที', + mm : '%d นาที', + h : '1 ชั่วโมง', + hh : '%d ชั่วโมง', + d : '1 วัน', + dd : '%d วัน', + M : '1 เดือน', + MM : '%d เดือน', + y : '1 ปี', + yy : '%d ปี' + } +});
@@ -0,0 +1,53 @@
+//! moment.js locale configuration +//! locale : Tagalog (Philippines) [tl-ph] +//! author : Dan Hagman + +import moment from '../moment'; + +export default moment.defineLocale('tl-ph', { + months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'), + monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'), + weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'), + weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'), + weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'MM/D/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY HH:mm', + LLLL : 'dddd, MMMM DD, YYYY HH:mm' + }, + calendar : { + sameDay: '[Ngayon sa] LT', + nextDay: '[Bukas sa] LT', + nextWeek: 'dddd [sa] LT', + lastDay: '[Kahapon sa] LT', + lastWeek: 'dddd [huling linggo] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'sa loob ng %s', + past : '%s ang nakalipas', + s : 'ilang segundo', + m : 'isang minuto', + mm : '%d minuto', + h : 'isang oras', + hh : '%d oras', + d : 'isang araw', + dd : '%d araw', + M : 'isang buwan', + MM : '%d buwan', + y : 'isang taon', + yy : '%d taon' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,110 @@
+//! moment.js locale configuration +//! locale : Klingon [tlh] +//! author : Dominika Kruk : https://github.com/amaranthrose + +import moment from '../moment'; + +var numbersNouns = 'pagh_wa’_cha’_wej_loS_vagh_jav_Soch_chorgh_Hut'.split('_'); + +function translateFuture(output) { + var time = output; + time = (output.indexOf('jaj') !== -1) ? + time.slice(0, -3) + 'leS' : + (output.indexOf('jar') !== -1) ? + time.slice(0, -3) + 'waQ' : + (output.indexOf('DIS') !== -1) ? + time.slice(0, -3) + 'nem' : + time + ' pIq'; + return time; +} + +function translatePast(output) { + var time = output; + time = (output.indexOf('jaj') !== -1) ? + time.slice(0, -3) + 'Hu’' : + (output.indexOf('jar') !== -1) ? + time.slice(0, -3) + 'wen' : + (output.indexOf('DIS') !== -1) ? + time.slice(0, -3) + 'ben' : + time + ' ret'; + return time; +} + +function translate(number, withoutSuffix, string, isFuture) { + var numberNoun = numberAsNoun(number); + switch (string) { + case 'mm': + return numberNoun + ' tup'; + case 'hh': + return numberNoun + ' rep'; + case 'dd': + return numberNoun + ' jaj'; + case 'MM': + return numberNoun + ' jar'; + case 'yy': + return numberNoun + ' DIS'; + } +} + +function numberAsNoun(number) { + var hundred = Math.floor((number % 1000) / 100), + ten = Math.floor((number % 100) / 10), + one = number % 10, + word = ''; + if (hundred > 0) { + word += numbersNouns[hundred] + 'vatlh'; + } + if (ten > 0) { + word += ((word !== '') ? ' ' : '') + numbersNouns[ten] + 'maH'; + } + if (one > 0) { + word += ((word !== '') ? ' ' : '') + numbersNouns[one]; + } + return (word === '') ? 'pagh' : word; +} + +export default moment.defineLocale('tlh', { + months : 'tera’ jar wa’_tera’ jar cha’_tera’ jar wej_tera’ jar loS_tera’ jar vagh_tera’ jar jav_tera’ jar Soch_tera’ jar chorgh_tera’ jar Hut_tera’ jar wa’maH_tera’ jar wa’maH wa’_tera’ jar wa’maH cha’'.split('_'), + monthsShort : 'jar wa’_jar cha’_jar wej_jar loS_jar vagh_jar jav_jar Soch_jar chorgh_jar Hut_jar wa’maH_jar wa’maH wa’_jar wa’maH cha’'.split('_'), + monthsParseExact : true, + weekdays : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'), + weekdaysShort : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'), + weekdaysMin : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[DaHjaj] LT', + nextDay: '[wa’leS] LT', + nextWeek: 'LLL', + lastDay: '[wa’Hu’] LT', + lastWeek: 'LLL', + sameElse: 'L' + }, + relativeTime : { + future : translateFuture, + past : translatePast, + s : 'puS lup', + m : 'wa’ tup', + mm : translate, + h : 'wa’ rep', + hh : translate, + d : 'wa’ jaj', + dd : translate, + M : 'wa’ jar', + MM : translate, + y : 'wa’ DIS', + yy : translate + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +});
@@ -0,0 +1,81 @@
+//! moment.js locale configuration +//! locale : Turkish [tr] +//! authors : Erhan Gundogan : https://github.com/erhangundogan, +//! Burak Yiğit Kaya: https://github.com/BYK + +import moment from '../moment'; + +var suffixes = { + 1: '\'inci', + 5: '\'inci', + 8: '\'inci', + 70: '\'inci', + 80: '\'inci', + 2: '\'nci', + 7: '\'nci', + 20: '\'nci', + 50: '\'nci', + 3: '\'üncü', + 4: '\'üncü', + 100: '\'üncü', + 6: '\'ncı', + 9: '\'uncu', + 10: '\'uncu', + 30: '\'uncu', + 60: '\'ıncı', + 90: '\'ıncı' +}; + +export default moment.defineLocale('tr', { + months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'), + monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'), + weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'), + weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'), + weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[bugün saat] LT', + nextDay : '[yarın saat] LT', + nextWeek : '[haftaya] dddd [saat] LT', + lastDay : '[dün] LT', + lastWeek : '[geçen hafta] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s sonra', + past : '%s önce', + s : 'birkaç saniye', + m : 'bir dakika', + mm : '%d dakika', + h : 'bir saat', + hh : '%d saat', + d : 'bir gün', + dd : '%d gün', + M : 'bir ay', + MM : '%d ay', + y : 'bir yıl', + yy : '%d yıl' + }, + ordinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/, + ordinal : function (number) { + if (number === 0) { // special case for zero + return number + '\'ıncı'; + } + var a = number % 10, + b = number % 100 - a, + c = number >= 100 ? 100 : null; + return number + (suffixes[a] || suffixes[b] || suffixes[c]); + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,82 @@
+//! moment.js locale configuration +//! locale : Talossan [tzl] +//! author : Robin van der Vliet : https://github.com/robin0van0der0v with the help of Iustì Canun + + +import moment from '../moment'; + +// After the year there should be a slash and the amount of years since December 26, 1979 in Roman numerals. +// This is currently too difficult (maybe even impossible) to add. +export default moment.defineLocale('tzl', { + months : 'Januar_Fevraglh_Març_Avrïu_Mai_Gün_Julia_Guscht_Setemvar_Listopäts_Noemvar_Zecemvar'.split('_'), + monthsShort : 'Jan_Fev_Mar_Avr_Mai_Gün_Jul_Gus_Set_Lis_Noe_Zec'.split('_'), + weekdays : 'Súladi_Lúneçi_Maitzi_Márcuri_Xhúadi_Viénerçi_Sáturi'.split('_'), + weekdaysShort : 'Súl_Lún_Mai_Már_Xhú_Vié_Sát'.split('_'), + weekdaysMin : 'Sú_Lú_Ma_Má_Xh_Vi_Sá'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'HH.mm.ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM [dallas] YYYY', + LLL : 'D. MMMM [dallas] YYYY HH.mm', + LLLL : 'dddd, [li] D. MMMM [dallas] YYYY HH.mm' + }, + meridiemParse: /d\'o|d\'a/i, + isPM : function (input) { + return 'd\'o' === input.toLowerCase(); + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'd\'o' : 'D\'O'; + } else { + return isLower ? 'd\'a' : 'D\'A'; + } + }, + calendar : { + sameDay : '[oxhi à] LT', + nextDay : '[demà à] LT', + nextWeek : 'dddd [à] LT', + lastDay : '[ieiri à] LT', + lastWeek : '[sür el] dddd [lasteu à] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'osprei %s', + past : 'ja%s', + s : processRelativeTime, + m : processRelativeTime, + mm : processRelativeTime, + h : processRelativeTime, + hh : processRelativeTime, + d : processRelativeTime, + dd : processRelativeTime, + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + ordinal : '%d.', + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); + +function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 's': ['viensas secunds', '\'iensas secunds'], + 'm': ['\'n míut', '\'iens míut'], + 'mm': [number + ' míuts', '' + number + ' míuts'], + 'h': ['\'n þora', '\'iensa þora'], + 'hh': [number + ' þoras', '' + number + ' þoras'], + 'd': ['\'n ziua', '\'iensa ziua'], + 'dd': [number + ' ziuas', '' + number + ' ziuas'], + 'M': ['\'n mes', '\'iens mes'], + 'MM': [number + ' mesen', '' + number + ' mesen'], + 'y': ['\'n ar', '\'iens ar'], + 'yy': [number + ' ars', '' + number + ' ars'] + }; + return isFuture ? format[key][0] : (withoutSuffix ? format[key][0] : format[key][1]); +} +
@@ -0,0 +1,49 @@
+//! moment.js locale configuration +//! locale : Central Atlas Tamazight Latin [tzm-latn] +//! author : Abdel Said : https://github.com/abdelsaid + +import moment from '../moment'; + +export default moment.defineLocale('tzm-latn', { + months : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'), + monthsShort : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'), + weekdays : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), + weekdaysShort : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), + weekdaysMin : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[asdkh g] LT', + nextDay: '[aska g] LT', + nextWeek: 'dddd [g] LT', + lastDay: '[assant g] LT', + lastWeek: 'dddd [g] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'dadkh s yan %s', + past : 'yan %s', + s : 'imik', + m : 'minuḍ', + mm : '%d minuḍ', + h : 'saɛa', + hh : '%d tassaɛin', + d : 'ass', + dd : '%d ossan', + M : 'ayowr', + MM : '%d iyyirn', + y : 'asgas', + yy : '%d isgasn' + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,49 @@
+//! moment.js locale configuration +//! locale : Central Atlas Tamazight [tzm] +//! author : Abdel Said : https://github.com/abdelsaid + +import moment from '../moment'; + +export default moment.defineLocale('tzm', { + months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd D MMMM YYYY HH:mm' + }, + calendar : { + sameDay: '[ⴰⵙⴷⵅ ⴴ] LT', + nextDay: '[ⴰⵙⴽⴰ ⴴ] LT', + nextWeek: 'dddd [ⴴ] LT', + lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT', + lastWeek: 'dddd [ⴴ] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s', + past : 'ⵢⴰⵏ %s', + s : 'ⵉⵎⵉⴽ', + m : 'ⵎⵉⵏⵓⴺ', + mm : '%d ⵎⵉⵏⵓⴺ', + h : 'ⵙⴰⵄⴰ', + hh : '%d ⵜⴰⵙⵙⴰⵄⵉⵏ', + d : 'ⴰⵙⵙ', + dd : '%d oⵙⵙⴰⵏ', + M : 'ⴰⵢoⵓⵔ', + MM : '%d ⵉⵢⵢⵉⵔⵏ', + y : 'ⴰⵙⴳⴰⵙ', + yy : '%d ⵉⵙⴳⴰⵙⵏ' + }, + week : { + dow : 6, // Saturday is the first day of the week. + doy : 12 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,137 @@
+//! moment.js locale configuration +//! locale : Ukrainian [uk] +//! author : zemlanin : https://github.com/zemlanin +//! Author : Menelion Elensúle : https://github.com/Oire + +import moment from '../moment'; + +function plural(word, num) { + var forms = word.split('_'); + return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]); +} +function relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'хвилина_хвилини_хвилин' : 'хвилину_хвилини_хвилин', + 'hh': withoutSuffix ? 'година_години_годин' : 'годину_години_годин', + 'dd': 'день_дні_днів', + 'MM': 'місяць_місяці_місяців', + 'yy': 'рік_роки_років' + }; + if (key === 'm') { + return withoutSuffix ? 'хвилина' : 'хвилину'; + } + else if (key === 'h') { + return withoutSuffix ? 'година' : 'годину'; + } + else { + return number + ' ' + plural(format[key], +number); + } +} +function weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'), + 'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'), + 'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_') + }, + nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ? + 'accusative' : + ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ? + 'genitive' : + 'nominative'); + return weekdays[nounCase][m.day()]; +} +function processHoursFunction(str) { + return function () { + return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT'; + }; +} + +export default moment.defineLocale('uk', { + months : { + 'format': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_'), + 'standalone': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_') + }, + monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'), + weekdays : weekdaysCaseReplace, + weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D MMMM YYYY р.', + LLL : 'D MMMM YYYY р., HH:mm', + LLLL : 'dddd, D MMMM YYYY р., HH:mm' + }, + calendar : { + sameDay: processHoursFunction('[Сьогодні '), + nextDay: processHoursFunction('[Завтра '), + lastDay: processHoursFunction('[Вчора '), + nextWeek: processHoursFunction('[У] dddd ['), + lastWeek: function () { + switch (this.day()) { + case 0: + case 3: + case 5: + case 6: + return processHoursFunction('[Минулої] dddd [').call(this); + case 1: + case 2: + case 4: + return processHoursFunction('[Минулого] dddd [').call(this); + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'за %s', + past : '%s тому', + s : 'декілька секунд', + m : relativeTimeWithPlural, + mm : relativeTimeWithPlural, + h : 'годину', + hh : relativeTimeWithPlural, + d : 'день', + dd : relativeTimeWithPlural, + M : 'місяць', + MM : relativeTimeWithPlural, + y : 'рік', + yy : relativeTimeWithPlural + }, + // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason + meridiemParse: /ночі|ранку|дня|вечора/, + isPM: function (input) { + return /^(дня|вечора)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночі'; + } else if (hour < 12) { + return 'ранку'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечора'; + } + }, + ordinalParse: /\d{1,2}-(й|го)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + case 'w': + case 'W': + return number + '-й'; + case 'D': + return number + '-го'; + default: + return number; + } + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 1st is the first week of the year. + } +}); +
@@ -0,0 +1,49 @@
+//! moment.js locale configuration +//! locale : Uzbek [uz] +//! author : Sardor Muminov : https://github.com/muminoff + +import moment from '../moment'; + +export default moment.defineLocale('uz', { + months : 'январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр'.split('_'), + monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'), + weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'), + weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'), + weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'D MMMM YYYY, dddd HH:mm' + }, + calendar : { + sameDay : '[Бугун соат] LT [да]', + nextDay : '[Эртага] LT [да]', + nextWeek : 'dddd [куни соат] LT [да]', + lastDay : '[Кеча соат] LT [да]', + lastWeek : '[Утган] dddd [куни соат] LT [да]', + sameElse : 'L' + }, + relativeTime : { + future : 'Якин %s ичида', + past : 'Бир неча %s олдин', + s : 'фурсат', + m : 'бир дакика', + mm : '%d дакика', + h : 'бир соат', + hh : '%d соат', + d : 'бир кун', + dd : '%d кун', + M : 'бир ой', + MM : '%d ой', + y : 'бир йил', + yy : '%d йил' + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,70 @@
+//! moment.js locale configuration +//! locale : Vietnamese [vi] +//! author : Bang Nguyen : https://github.com/bangnk + +import moment from '../moment'; + +export default moment.defineLocale('vi', { + months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'), + monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'), + monthsParseExact : true, + weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'), + weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + weekdaysParseExact : true, + meridiemParse: /sa|ch/i, + isPM : function (input) { + return /^ch$/i.test(input); + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower ? 'sa' : 'SA'; + } else { + return isLower ? 'ch' : 'CH'; + } + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM [năm] YYYY', + LLL : 'D MMMM [năm] YYYY HH:mm', + LLLL : 'dddd, D MMMM [năm] YYYY HH:mm', + l : 'DD/M/YYYY', + ll : 'D MMM YYYY', + lll : 'D MMM YYYY HH:mm', + llll : 'ddd, D MMM YYYY HH:mm' + }, + calendar : { + sameDay: '[Hôm nay lúc] LT', + nextDay: '[Ngày mai lúc] LT', + nextWeek: 'dddd [tuần tới lúc] LT', + lastDay: '[Hôm qua lúc] LT', + lastWeek: 'dddd [tuần rồi lúc] LT', + sameElse: 'L' + }, + relativeTime : { + future : '%s tới', + past : '%s trước', + s : 'vài giây', + m : 'một phút', + mm : '%d phút', + h : 'một giờ', + hh : '%d giờ', + d : 'một ngày', + dd : '%d ngày', + M : 'một tháng', + MM : '%d tháng', + y : 'một năm', + yy : '%d năm' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,58 @@
+//! moment.js locale configuration +//! locale : Pseudo [x-pseudo] +//! author : Andrew Hood : https://github.com/andrewhood125 + +import moment from '../moment'; + +export default moment.defineLocale('x-pseudo', { + months : 'J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér'.split('_'), + monthsShort : 'J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc'.split('_'), + monthsParseExact : true, + weekdays : 'S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý'.split('_'), + weekdaysShort : 'S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát'.split('_'), + weekdaysMin : 'S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá'.split('_'), + weekdaysParseExact : true, + longDateFormat : { + LT : 'HH:mm', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY HH:mm', + LLLL : 'dddd, D MMMM YYYY HH:mm' + }, + calendar : { + sameDay : '[T~ódá~ý át] LT', + nextDay : '[T~ómó~rró~w át] LT', + nextWeek : 'dddd [át] LT', + lastDay : '[Ý~ést~érdá~ý át] LT', + lastWeek : '[L~ást] dddd [át] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'í~ñ %s', + past : '%s á~gó', + s : 'á ~féw ~sécó~ñds', + m : 'á ~míñ~úté', + mm : '%d m~íñú~tés', + h : 'á~ñ hó~úr', + hh : '%d h~óúrs', + d : 'á ~dáý', + dd : '%d d~áýs', + M : 'á ~móñ~th', + MM : '%d m~óñt~hs', + y : 'á ~ýéár', + yy : '%d ý~éárs' + }, + ordinalParse: /\d{1,2}(th|st|nd|rd)/, + ordinal : function (number) { + var b = number % 10, + output = (~~(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + }, + week : { + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +});
@@ -0,0 +1,118 @@
+//! moment.js locale configuration +//! locale : Chinese (China) [zh-cn] +//! author : suupic : https://github.com/suupic +//! author : Zeno Zeng : https://github.com/zenozeng + +import moment from '../moment'; + +export default moment.defineLocale('zh-cn', { + months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'), + monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'), + weekdaysShort : '周日_周一_周二_周三_周四_周五_周六'.split('_'), + weekdaysMin : '日_一_二_三_四_五_六'.split('_'), + longDateFormat : { + LT : 'Ah点mm分', + LTS : 'Ah点m分s秒', + L : 'YYYY-MM-DD', + LL : 'YYYY年MMMD日', + LLL : 'YYYY年MMMD日Ah点mm分', + LLLL : 'YYYY年MMMD日ddddAh点mm分', + l : 'YYYY-MM-DD', + ll : 'YYYY年MMMD日', + lll : 'YYYY年MMMD日Ah点mm分', + llll : 'YYYY年MMMD日ddddAh点mm分' + }, + meridiemParse: /凌晨|早上|上午|中午|下午|晚上/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '凌晨' || meridiem === '早上' || + meridiem === '上午') { + return hour; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } else { + // '中午' + return hour >= 11 ? hour : hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 600) { + return '凌晨'; + } else if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : function () { + return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT'; + }, + nextDay : function () { + return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT'; + }, + lastDay : function () { + return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT'; + }, + nextWeek : function () { + var startOfWeek, prefix; + startOfWeek = moment().startOf('week'); + prefix = this.diff(startOfWeek, 'days') >= 7 ? '[下]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + lastWeek : function () { + var startOfWeek, prefix; + startOfWeek = moment().startOf('week'); + prefix = this.unix() < startOfWeek.unix() ? '[上]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + sameElse : 'LL' + }, + ordinalParse: /\d{1,2}(日|月|周)/, + ordinal : function (number, period) { + switch (period) { + case 'd': + case 'D': + case 'DDD': + return number + '日'; + case 'M': + return number + '月'; + case 'w': + case 'W': + return number + '周'; + default: + return number; + } + }, + relativeTime : { + future : '%s内', + past : '%s前', + s : '几秒', + m : '1 分钟', + mm : '%d 分钟', + h : '1 小时', + hh : '%d 小时', + d : '1 天', + dd : '%d 天', + M : '1 个月', + MM : '%d 个月', + y : '1 年', + yy : '%d 年' + }, + week : { + // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效 + dow : 1, // Monday is the first day of the week. + doy : 4 // The week that contains Jan 4th is the first week of the year. + } +}); +
@@ -0,0 +1,94 @@
+//! moment.js locale configuration +//! locale : Chinese (Taiwan) [zh-tw] +//! author : Ben : https://github.com/ben-lin +//! author : Chris Lam : https://github.com/hehachris + +import moment from '../moment'; + +export default moment.defineLocale('zh-tw', { + months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'), + monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), + weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'), + weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'), + weekdaysMin : '日_一_二_三_四_五_六'.split('_'), + longDateFormat : { + LT : 'Ah點mm分', + LTS : 'Ah點m分s秒', + L : 'YYYY年MMMD日', + LL : 'YYYY年MMMD日', + LLL : 'YYYY年MMMD日Ah點mm分', + LLLL : 'YYYY年MMMD日ddddAh點mm分', + l : 'YYYY年MMMD日', + ll : 'YYYY年MMMD日', + lll : 'YYYY年MMMD日Ah點mm分', + llll : 'YYYY年MMMD日ddddAh點mm分' + }, + meridiemParse: /凌晨|早上|上午|中午|下午|晚上/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') { + return hour; + } else if (meridiem === '中午') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 600) { + return '凌晨'; + } else if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : '[今天]LT', + nextDay : '[明天]LT', + nextWeek : '[下]ddddLT', + lastDay : '[昨天]LT', + lastWeek : '[上]ddddLT', + sameElse : 'L' + }, + ordinalParse: /\d{1,2}(日|月|週)/, + ordinal : function (number, period) { + switch (period) { + case 'd' : + case 'D' : + case 'DDD' : + return number + '日'; + case 'M' : + return number + '月'; + case 'w' : + case 'W' : + return number + '週'; + default : + return number; + } + }, + relativeTime : { + future : '%s內', + past : '%s前', + s : '幾秒', + m : '1 分鐘', + mm : '%d 分鐘', + h : '1 小時', + hh : '%d 小時', + d : '1 天', + dd : '%d 天', + M : '1 個月', + MM : '%d 個月', + y : '1 年', + yy : '%d 年' + } +});
@@ -0,0 +1,82 @@
+//! moment.js +//! version : 2.14.1 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com + +import { hooks as moment, setHookCallback } from './lib/utils/hooks'; + +moment.version = '2.14.1'; + +import { + min, + max, + now, + isMoment, + momentPrototype as fn, + createUTC as utc, + createUnix as unix, + createLocal as local, + createInvalid as invalid, + createInZone as parseZone +} from './lib/moment/moment'; + +import { + getCalendarFormat +} from './lib/moment/calendar'; + +import { + defineLocale, + updateLocale, + getSetGlobalLocale as locale, + getLocale as localeData, + listLocales as locales, + listMonths as months, + listMonthsShort as monthsShort, + listWeekdays as weekdays, + listWeekdaysMin as weekdaysMin, + listWeekdaysShort as weekdaysShort +} from './lib/locale/locale'; + +import { + isDuration, + createDuration as duration, + getSetRelativeTimeRounding as relativeTimeRounding, + getSetRelativeTimeThreshold as relativeTimeThreshold +} from './lib/duration/duration'; + +import { normalizeUnits } from './lib/units/units'; + +import isDate from './lib/utils/is-date'; + +setHookCallback(local); + +moment.fn = fn; +moment.min = min; +moment.max = max; +moment.now = now; +moment.utc = utc; +moment.unix = unix; +moment.months = months; +moment.isDate = isDate; +moment.locale = locale; +moment.invalid = invalid; +moment.duration = duration; +moment.isMoment = isMoment; +moment.weekdays = weekdays; +moment.parseZone = parseZone; +moment.localeData = localeData; +moment.isDuration = isDuration; +moment.monthsShort = monthsShort; +moment.weekdaysMin = weekdaysMin; +moment.defineLocale = defineLocale; +moment.updateLocale = updateLocale; +moment.locales = locales; +moment.weekdaysShort = weekdaysShort; +moment.normalizeUnits = normalizeUnits; +moment.relativeTimeRounding = relativeTimeRounding; +moment.relativeTimeThreshold = relativeTimeThreshold; +moment.calendarFormat = getCalendarFormat; +moment.prototype = fn; + +export default moment;
@@ -0,0 +1,18 @@
+.idea +*.iml +npm-debug.log +dump.rdb +node_modules +results.tap +results.xml +npm-shrinkwrap.json +config.json +.DS_Store +*/.DS_Store +*/*/.DS_Store +._* +*/._* +*/*/._* +coverage.* +lib-cov +complexity.md
@@ -0,0 +1,9 @@
+language: node_js + +node_js: + - 0.10 + - 4.0 + - 4 + +sudo: false +
@@ -0,0 +1,32 @@
+# API Reference + +## `Topo` +The `Topo` object is the container for topologically sorting a list of nodes with non-circular interdependencies. + +### `new Topo()` +Creates a new `Topo` object. + +### `topo.add(nodes, [options])` +Specifies an additional node or list of nodes to be topologically sorted where: + - `nodes` - a mixed value or array of mixed values to be added as nodes to the topologically sorted list. + - `options` - optional sorting information about the `nodes`: + - `group` - a string naming the group to which `nodes` should be assigned. The group name `'?'` is reserved. + - `before` - a string or array of strings specifying the groups that `nodes` must precede in the topological sort. + - `after` - a string or array of strings specifying the groups that `nodes` must succeed in the topological sort. + - `sort` - a numerical value used to sort items when performing a `topo.merge()`. + +Returns an array of the topologically sorted nodes. + +### `topo.nodes` +An array of the topologically sorted nodes. This list is renewed upon each call to [`topo.add()`](#topoaddnodes-options). + +### `topo.merge(others)` +Merges another `Topo` object into the current object where: +- `others` - the other object or array of objects to be merged into the current one. `null` + values are ignored. + +Returns an array of the topologically sorted nodes. Will throw if a dependency error is found as a result of the +combined items. + +If the order in which items have been added to each list matters, use the `sort` option in `topo.add()` with an incrementing +value providing an absolute sort order among all items added to either object.
@@ -0,0 +1,16 @@
+# How to contribute +We welcome contributions from the community and are pleased to have them. Please follow this guide when logging issues or making code changes. + +## Logging Issues +All issues should be created using the [new issue form](https://github.com/hapijs/topo/issues/new). Clearly describe the issue including steps +to reproduce if there are any. Also, make sure to indicate the earliest version that has the issue being reported. + +## Patching Code + +Code changes are welcome and should follow the guidelines below. + +* Fork the repository on GitHub. +* Fix the issue ensuring that your code follows the [style guide](https://github.com/hapijs/contrib/blob/master/Style.md). +* Add tests for your new code ensuring that you have 100% code coverage (we can help you reach 100% but will not merge without it). + * Run `npm test` to generate a report of test coverage +* [Pull requests](http://help.github.com/send-pull-requests/) should be made to the [master branch](https://github.com/hapijs/topo/tree/master).
@@ -0,0 +1,28 @@
+Copyright (c) 2012-2014, Walmart and other contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The names of any contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * * * + +The complete list of contributors can be found at: https://github.com/hapijs/topo/graphs/contributors
@@ -0,0 +1,29 @@
+# topo + +Topological sorting with grouping support. + +[](http://travis-ci.org/hapijs/topo) + +Lead Maintainer: [Devin Ivy](https://github.com/devinivy) + +## Usage + +See the [API Reference](API.md) + +**Example** +```node +var Topo = require('topo'); + +var morning = new Topo(); + +morning.add('Nap', { after: ['breakfast', 'prep'] }); + +morning.add([ + 'Make toast', + 'Pour juice' +], { before: 'breakfast', group: 'prep' }); + +morning.add('Eat breakfast', { group: 'breakfast' }); + +morning.nodes; // ['Make toast', 'Pour juice', 'Eat breakfast', 'Nap'] +```
@@ -0,0 +1,231 @@
+// Load modules + +var Hoek = require('hoek'); + + +// Declare internals + +var internals = {}; + + +exports = module.exports = internals.Topo = function () { + + this._items = []; + this.nodes = []; +}; + + +internals.Topo.prototype.add = function (nodes, options) { + + var self = this; + + options = options || {}; + + // Validate rules + + var before = [].concat(options.before || []); + var after = [].concat(options.after || []); + var group = options.group || '?'; + var sort = options.sort || 0; // Used for merging only + + Hoek.assert(before.indexOf(group) === -1, 'Item cannot come before itself:', group); + Hoek.assert(before.indexOf('?') === -1, 'Item cannot come before unassociated items'); + Hoek.assert(after.indexOf(group) === -1, 'Item cannot come after itself:', group); + Hoek.assert(after.indexOf('?') === -1, 'Item cannot come after unassociated items'); + + ([].concat(nodes)).forEach(function (node, i) { + + var item = { + seq: self._items.length, + sort: sort, + before: before, + after: after, + group: group, + node: node + }; + + self._items.push(item); + }); + + // Insert event + + var error = this._sort(); + Hoek.assert(!error, 'item', (group !== '?' ? 'added into group ' + group : ''), 'created a dependencies error'); + + return this.nodes; +}; + + +internals.Topo.prototype.merge = function (others) { + + others = [].concat(others); + for (var o = 0, ol = others.length; o < ol; ++o) { + var other = others[o]; + if (other) { + for (var i = 0, il = other._items.length; i < il; ++i) { + var item = Hoek.shallow(other._items[i]); + this._items.push(item); + } + } + } + + // Sort items + + this._items.sort(internals.mergeSort); + for (i = 0, il = this._items.length; i < il; ++i) { + this._items[i].seq = i; + } + + var error = this._sort(); + Hoek.assert(!error, 'merge created a dependencies error'); + + return this.nodes; +}; + + +internals.mergeSort = function (a, b) { + + return a.sort === b.sort ? 0 : (a.sort < b.sort ? -1 : 1); +}; + + +internals.Topo.prototype._sort = function () { + + // Construct graph + + var groups = {}; + var graph = {}; + var graphAfters = {}; + + for (var i = 0, il = this._items.length; i < il; ++i) { + var item = this._items[i]; + var seq = item.seq; // Unique across all items + var group = item.group; + + // Determine Groups + + groups[group] = groups[group] || []; + groups[group].push(seq); + + // Build intermediary graph using 'before' + + graph[seq] = item.before; + + // Build second intermediary graph with 'after' + + var after = item.after; + for (var j = 0, jl = after.length; j < jl; ++j) { + graphAfters[after[j]] = (graphAfters[after[j]] || []).concat(seq); + } + } + + // Expand intermediary graph + + var graphNodes = Object.keys(graph); + for (i = 0, il = graphNodes.length; i < il; ++i) { + var node = graphNodes[i]; + var expandedGroups = []; + + var graphNodeItems = Object.keys(graph[node]); + for (j = 0, jl = graphNodeItems.length; j < jl; ++j) { + group = graph[node][graphNodeItems[j]]; + groups[group] = groups[group] || []; + + for (var k = 0, kl = groups[group].length; k < kl; ++k) { + + expandedGroups.push(groups[group][k]); + } + } + graph[node] = expandedGroups; + } + + // Merge intermediary graph using graphAfters into final graph + + var afterNodes = Object.keys(graphAfters); + for (i = 0, il = afterNodes.length; i < il; ++i) { + group = afterNodes[i]; + + if (groups[group]) { + for (j = 0, jl = groups[group].length; j < jl; ++j) { + node = groups[group][j]; + graph[node] = graph[node].concat(graphAfters[group]); + } + } + } + + // Compile ancestors + + var children; + var ancestors = {}; + graphNodes = Object.keys(graph); + for (i = 0, il = graphNodes.length; i < il; ++i) { + node = graphNodes[i]; + children = graph[node]; + + for (j = 0, jl = children.length; j < jl; ++j) { + ancestors[children[j]] = (ancestors[children[j]] || []).concat(node); + } + } + + // Topo sort + + var visited = {}; + var sorted = []; + + for (i = 0, il = this._items.length; i < il; ++i) { + var next = i; + + if (ancestors[i]) { + next = null; + for (j = 0, jl = this._items.length; j < jl; ++j) { + if (visited[j] === true) { + continue; + } + + if (!ancestors[j]) { + ancestors[j] = []; + } + + var shouldSeeCount = ancestors[j].length; + var seenCount = 0; + for (var l = 0, ll = shouldSeeCount; l < ll; ++l) { + if (sorted.indexOf(ancestors[j][l]) >= 0) { + ++seenCount; + } + } + + if (seenCount === shouldSeeCount) { + next = j; + break; + } + } + } + + if (next !== null) { + next = next.toString(); // Normalize to string TODO: replace with seq + visited[next] = true; + sorted.push(next); + } + } + + if (sorted.length !== this._items.length) { + return new Error('Invalid dependencies'); + } + + var seqIndex = {}; + for (i = 0, il = this._items.length; i < il; ++i) { + + item = this._items[i]; + seqIndex[item.seq] = item; + } + + var sortedNodes = []; + this._items = sorted.map(function (value) { + + var sortedItem = seqIndex[value]; + sortedNodes.push(sortedItem.node); + return sortedItem; + }); + + this.nodes = sortedNodes; +};
@@ -0,0 +1,60 @@
+{ + "name": "topo", + "description": "Topological sorting with grouping support", + "version": "1.1.0", + "repository": { + "type": "git", + "url": "git://github.com/hapijs/topo" + }, + "main": "lib/index.js", + "keywords": [ + "topological", + "sort", + "toposort", + "topsort" + ], + "engines": { + "node": ">=0.10.40" + }, + "dependencies": { + "hoek": "2.x.x" + }, + "devDependencies": { + "lab": "6.x.x", + "code": "1.x.x" + }, + "scripts": { + "test": "lab -a code -t 100 -L", + "test-cov-html": "lab -a code -t 100 -L -r html -o coverage.html" + }, + "license": "BSD-3-Clause", + "gitHead": "4cbd80aba9674c9c338a19ebafc2bfa29f664a29", + "bugs": { + "url": "https://github.com/hapijs/topo/issues" + }, + "homepage": "https://github.com/hapijs/topo", + "_id": "topo@1.1.0", + "_shasum": "e9d751615d1bb87dc865db182fa1ca0a5ef536d5", + "_from": "topo@>=1.0.0 <2.0.0", + "_npmVersion": "1.4.28", + "_npmUser": { + "name": "devinivy", + "email": "devin@bigroomstudios.com" + }, + "maintainers": [ + { + "name": "hueniverse", + "email": "eran@hammer.io" + }, + { + "name": "devinivy", + "email": "devin@bigroomstudios.com" + } + ], + "dist": { + "shasum": "e9d751615d1bb87dc865db182fa1ca0a5ef536d5", + "tarball": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz" +}
@@ -0,0 +1,266 @@
+// Load modules + +var Code = require('code'); +var Lab = require('lab'); +var Hoek = require('hoek'); +var Topo = require('..'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +describe('Topo', function () { + + var testDeps = function (scenario) { + + var topo = new Topo(); + scenario.forEach(function (record, i) { + + var options = record.before || record.after || record.group ? { before: record.before, after: record.after, group: record.group } : null; + topo.add(record.id, options); + }); + + return topo.nodes.join(''); + }; + + it('sorts dependencies', function (done) { + + var scenario = [ + { id: '0', before: 'a' }, + { id: '1', after: 'f', group: 'a' }, + { id: '2', before: 'a' }, + { id: '3', before: ['b', 'c'], group: 'a' }, + { id: '4', after: 'c', group: 'b' }, + { id: '5', group: 'c' }, + { id: '6', group: 'd' }, + { id: '7', group: 'e' }, + { id: '8', before: 'd' }, + { id: '9', after: 'c', group: 'a' } + ]; + + expect(testDeps(scenario)).to.equal('0213547869'); + done(); + }); + + it('sorts dependencies (before as array)', function (done) { + + var scenario = [ + { id: '0', group: 'a' }, + { id: '1', group: 'b' }, + { id: '2', before: ['a', 'b'] } + ]; + + expect(testDeps(scenario)).to.equal('201'); + done(); + }); + + it('sorts dependencies (after as array)', function (done) { + + var scenario = [ + { id: '0', after: ['a', 'b'] }, + { id: '1', group: 'a' }, + { id: '2', group: 'b' } + ]; + + expect(testDeps(scenario)).to.equal('120'); + done(); + }); + + + it('sorts dependencies (seq)', function (done) { + + var scenario = [ + { id: '0' }, + { id: '1' }, + { id: '2' }, + { id: '3' } + ]; + + expect(testDeps(scenario)).to.equal('0123'); + done(); + }); + + it('sorts dependencies (explicitly using after or before)', function (done) { + + var set = '0123456789abcdefghijklmnopqrstuvwxyz'; + var groups = set.split(''); + + // Use Fisher-Yates for shuffling + + var fisherYates = function (array) { + + var i = array.length; + while (--i) { + var j = Math.floor(Math.random() * (i + 1)); + var tempi = array[i]; + var tempj = array[j]; + array[i] = tempj; + array[j] = tempi; + } + }; + + var scenarioAfter = []; + var scenarioBefore = []; + for (var i = 0, il = groups.length; i < il; ++i) { + var item = { + id: groups[i], + group: groups[i] + }; + var afterMod = { + after: i ? groups.slice(0, i) : [] + }; + var beforeMod = { + before: groups.slice(i + 1) + }; + + scenarioAfter.push(Hoek.applyToDefaults(item, afterMod)); + scenarioBefore.push(Hoek.applyToDefaults(item, beforeMod)); + } + + fisherYates(scenarioAfter); + expect(testDeps(scenarioAfter)).to.equal(set); + + fisherYates(scenarioBefore); + expect(testDeps(scenarioBefore)).to.equal(set); + done(); + }); + + it('throws on circular dependency', function (done) { + + var scenario = [ + { id: '0', before: 'a', group: 'b' }, + { id: '1', before: 'c', group: 'a' }, + { id: '2', before: 'b', group: 'c' } + ]; + + expect(function () { + + testDeps(scenario); + }).to.throw('item added into group c created a dependencies error'); + + done(); + }); + + describe('merge()', function () { + + it('merges objects', function (done) { + + var topo = new Topo(); + topo.add('0', { before: 'a' }); + topo.add('2', { before: 'a' }); + topo.add('4', { after: 'c', group: 'b' }); + topo.add('6', { group: 'd' }); + topo.add('8', { before: 'd' }); + expect(topo.nodes.join('')).to.equal('02486'); + + var other = new Topo(); + other.add('1', { after: 'f', group: 'a' }); + other.add('3', { before: ['b', 'c'], group: 'a' }); + other.add('5', { group: 'c' }); + other.add('7', { group: 'e' }); + other.add('9', { after: 'c', group: 'a' }); + expect(other.nodes.join('')).to.equal('13579'); + + topo.merge(other); + expect(topo.nodes.join('')).to.equal('0286135479'); + done(); + }); + + it('merges objects (explicit sort)', function (done) { + + var topo = new Topo(); + topo.add('0', { before: 'a', sort: 1 }); + topo.add('2', { before: 'a', sort: 2 }); + topo.add('4', { after: 'c', group: 'b', sort: 3 }); + topo.add('6', { group: 'd', sort: 4 }); + topo.add('8', { before: 'd', sort: 5 }); + expect(topo.nodes.join('')).to.equal('02486'); + + var other = new Topo(); + other.add('1', { after: 'f', group: 'a', sort: 6 }); + other.add('3', { before: ['b', 'c'], group: 'a', sort: 7 }); + other.add('5', { group: 'c', sort: 8 }); + other.add('7', { group: 'e', sort: 9 }); + other.add('9', { after: 'c', group: 'a', sort: 10 }); + expect(other.nodes.join('')).to.equal('13579'); + + topo.merge(other); + expect(topo.nodes.join('')).to.equal('0286135479'); + done(); + }); + + it('merges objects (mixed sort)', function (done) { + + var topo = new Topo(); + topo.add('0', { before: 'a', sort: 1 }); + topo.add('2', { before: 'a', sort: 3 }); + topo.add('4', { after: 'c', group: 'b', sort: 5 }); + topo.add('6', { group: 'd', sort: 7 }); + topo.add('8', { before: 'd', sort: 9 }); + expect(topo.nodes.join('')).to.equal('02486'); + + var other = new Topo(); + other.add('1', { after: 'f', group: 'a', sort: 2 }); + other.add('3', { before: ['b', 'c'], group: 'a', sort: 4 }); + other.add('5', { group: 'c', sort: 6 }); + other.add('7', { group: 'e', sort: 8 }); + other.add('9', { after: 'c', group: 'a', sort: 10 }); + expect(other.nodes.join('')).to.equal('13579'); + + topo.merge(other); + expect(topo.nodes.join('')).to.equal('0213547869'); + done(); + }); + + it('merges objects (multiple)', function (done) { + + var topo1 = new Topo(); + topo1.add('0', { before: 'a', sort: 1 }); + topo1.add('2', { before: 'a', sort: 3 }); + topo1.add('4', { after: 'c', group: 'b', sort: 5 }); + + var topo2 = new Topo(); + topo2.add('6', { group: 'd', sort: 7 }); + topo2.add('8', { before: 'd', sort: 9 }); + + var other = new Topo(); + other.add('1', { after: 'f', group: 'a', sort: 2 }); + other.add('3', { before: ['b', 'c'], group: 'a', sort: 4 }); + other.add('5', { group: 'c', sort: 6 }); + other.add('7', { group: 'e', sort: 8 }); + other.add('9', { after: 'c', group: 'a', sort: 10 }); + expect(other.nodes.join('')).to.equal('13579'); + + topo1.merge([topo2, null, other]); + expect(topo1.nodes.join('')).to.equal('0213547869'); + done(); + }); + + it('throws on circular dependency', function (done) { + + var topo = new Topo(); + topo.add('0', { before: 'a', group: 'b' }); + topo.add('1', { before: 'c', group: 'a' }); + + var other = new Topo(); + other.add('2', { before: 'b', group: 'c' }); + + expect(function () { + + topo.merge(other); + }).to.throw('merge created a dependencies error'); + + done(); + }); + }); +});
@@ -0,0 +1,67 @@
+{ + "name": "joi", + "description": "Object schema validation", + "version": "6.10.1", + "repository": { + "type": "git", + "url": "git://github.com/hapijs/joi.git" + }, + "main": "lib/index.js", + "keywords": [ + "hapi", + "schema", + "validation" + ], + "engines": { + "node": ">=0.10.40", + "npm": ">=2.0.0" + }, + "dependencies": { + "hoek": "2.x.x", + "topo": "1.x.x", + "isemail": "1.x.x", + "moment": "2.x.x" + }, + "devDependencies": { + "code": "1.x.x", + "lab": "6.x.x", + "markdown-toc": "0.11.x" + }, + "scripts": { + "test": "lab -t 100 -a code -L", + "test-cov-html": "lab -r html -o coverage.html -a code", + "toc": "node generate-readme-toc.js", + "version": "npm run toc && git add API.md" + }, + "license": "BSD-3-Clause", + "gitHead": "19c2e1cdefd557b8297f7cd55cc0fb4f261c2c8e", + "bugs": { + "url": "https://github.com/hapijs/joi/issues" + }, + "homepage": "https://github.com/hapijs/joi#readme", + "_id": "joi@6.10.1", + "_shasum": "4d50c318079122000fe5f16af1ff8e1917b77e06", + "_from": "joi@>=6.10.1 <7.0.0", + "_npmVersion": "3.5.0", + "_nodeVersion": "5.1.0", + "_npmUser": { + "name": "marsup", + "email": "marsup@gmail.com" + }, + "dist": { + "shasum": "4d50c318079122000fe5f16af1ff8e1917b77e06", + "tarball": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz" + }, + "maintainers": [ + { + "name": "hueniverse", + "email": "eran@hueniverse.com" + }, + { + "name": "marsup", + "email": "marsup@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz" +}
@@ -0,0 +1,488 @@
+// Load modules + +var Lab = require('lab'); +var Code = require('code'); +var Joi = require('..'); +var Helper = require('./helper'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +describe('alternatives', function () { + + it('fails when no alternatives are provided', function (done) { + + Joi.alternatives().validate('a', function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" not matching any of the allowed alternatives'); + done(); + }); + }); + + it('allows undefined when no alternatives are provided', function (done) { + + Joi.alternatives().validate(undefined, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('applies modifiers when higher priority converts', function (done) { + + var schema = Joi.object({ + a: [ + Joi.number(), + Joi.string() + ] + }); + + schema.validate({ a: '5' }, function (err, value) { + + expect(err).to.not.exist(); + expect(value.a).to.equal(5); + done(); + }); + }); + + it('applies modifiers when lower priority valid is a match', function (done) { + + var schema = Joi.object({ + a: [ + Joi.number(), + Joi.valid('5') + ] + }); + + schema.validate({ a: '5' }, function (err, value) { + + expect(err).to.not.exist(); + expect(value.a).to.equal(5); + done(); + }); + }); + + it('does not apply modifier if alternative fails', function (done) { + + var schema = Joi.object({ + a: [ + Joi.object({ c: Joi.any(), d: Joi.number() }).rename('b', 'c'), + { b: Joi.any(), d: Joi.string() } + ] + }); + + var input = { a: { b: 'any', d: 'string' } }; + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value.a.b).to.equal('any'); + done(); + }); + }); + + describe('#try', function () { + + it('throws when missing alternatives', function (done) { + + expect(function () { + + Joi.alternatives().try(); + }).to.throw('Cannot add other alternatives without at least one schema'); + done(); + }); + }); + + describe('#when', function () { + + it('throws on invalid ref (not string)', function (done) { + + expect(function () { + + Joi.alternatives().when(5, { is: 6, then: Joi.number() }); + }).to.throw('Invalid reference: 5'); + done(); + }); + + it('validates conditional alternatives', function (done) { + + var schema = { + a: Joi.alternatives().when('b', { is: 5, then: 'x', otherwise: 'y' }) + .try('z'), + b: Joi.any() + }; + + Helper.validate(schema, [ + [{ a: 'x', b: 5 }, true], + [{ a: 'x', b: 6 }, false], + [{ a: 'y', b: 5 }, false], + [{ a: 'y', b: 6 }, true], + [{ a: 'z', b: 5 }, true], + [{ a: 'z', b: 6 }, true] + ], done); + }); + + it('validates conditional alternatives (empty key)', function (done) { + + var schema = { + a: Joi.alternatives().when('', { is: 5, then: 'x', otherwise: 'y' }) + .try('z'), + '': Joi.any() + }; + + Helper.validate(schema, [ + [{ a: 'x', '': 5 }, true], + [{ a: 'x', '': 6 }, false], + [{ a: 'y', '': 5 }, false], + [{ a: 'y', '': 6 }, true], + [{ a: 'z', '': 5 }, true], + [{ a: 'z', '': 6 }, true] + ], done); + }); + + it('validates only then', function (done) { + + var schema = { + a: Joi.alternatives().when(Joi.ref('b'), { is: 5, then: 'x' }) + .try('z'), + b: Joi.any() + }; + + Helper.validate(schema, [ + [{ a: 'x', b: 5 }, true], + [{ a: 'x', b: 6 }, false], + [{ a: 'y', b: 5 }, false], + [{ a: 'y', b: 6 }, false], + [{ a: 'z', b: 5 }, true], + [{ a: 'z', b: 6 }, true] + ], done); + }); + + it('validates only otherwise', function (done) { + + var schema = { + a: Joi.alternatives().when('b', { is: 5, otherwise: 'y' }) + .try('z'), + b: Joi.any() + }; + + Helper.validate(schema, [ + [{ a: 'x', b: 5 }, false], + [{ a: 'x', b: 6 }, false], + [{ a: 'y', b: 5 }, false], + [{ a: 'y', b: 6 }, true], + [{ a: 'z', b: 5 }, true], + [{ a: 'z', b: 6 }, true] + ], done); + }); + + it('validates when is is null', function (done) { + + var schema = { + a: Joi.alternatives().when('b', { is: null, then: 'x', otherwise: Joi.number() }), + b: Joi.any() + }; + + Helper.validate(schema, [ + [{ a: 1 }, true], + [{ a: 'y' }, false], + [{ a: 'x', b: null }, true], + [{ a: 'y', b: null }, false], + [{ a: 1, b: null }, false] + ], done); + }); + + it('validates when is has ref', function (done) { + + var schema = { + a: Joi.alternatives().when('b', { is: Joi.ref('c'), then: 'x' }), + b: Joi.any(), + c: Joi.number() + }; + + Helper.validate(schema, [ + [{ a: 'x', b: 5, c: '5' }, true], + [{ a: 'x', b: 5, c: '1' }, false], + [{ a: 'x', b: '5', c: '5' }, false], + [{ a: 'y', b: 5, c: 5 }, false], + [{ a: 'y' }, false] + ], done); + }); + + it('validates when then has ref', function (done) { + + var schema = { + a: Joi.alternatives().when('b', { is: 5, then: Joi.ref('c') }), + b: Joi.any(), + c: Joi.number() + }; + + Helper.validate(schema, [ + [{ a: 'x', b: 5, c: '1' }, false], + [{ a: 1, b: 5, c: '1' }, true], + [{ a: '1', b: 5, c: '1' }, false] + ], done); + }); + + it('validates when otherwise has ref', function (done) { + + var schema = { + a: Joi.alternatives().when('b', { is: 6, otherwise: Joi.ref('c') }), + b: Joi.any(), + c: Joi.number() + }; + + Helper.validate(schema, [ + [{ a: 'x', b: 5, c: '1' }, false], + [{ a: 1, b: 5, c: '1' }, true], + [{ a: '1', b: 5, c: '1' }, false] + ], done); + }); + + it('validates when empty value', function (done) { + + var schema = { + a: Joi.alternatives().when('b', { is: true, then: Joi.required() }), + b: Joi.boolean().default(false) + }; + + Helper.validate(schema, [ + [{ b: false }, true], + [{ b: true }, true] // true because required() only applies to the one alternative + ], done); + }); + + it('validates when missing value', function (done) { + + var schema = Joi.object({ + a: Joi.alternatives().when('b', { is: 5, then: Joi.optional(), otherwise: Joi.required() }).required(), + b: Joi.number() + }); + + Helper.validate(schema, [ + [{ a: 1 }, true], + [{}, false], + [{ b: 1 }, false], + [{ a: 1, b: 1 }, true], + [{ a: 1, b: 5 }, true], + [{ b: 5 }, false] + ], done); + }); + }); + + describe('#describe', function () { + + it('describes when', function (done) { + + var schema = { + a: Joi.alternatives().when('b', { is: 5, then: 'x', otherwise: 'y' }) + .try('z'), + b: Joi.any() + }; + + var outcome = { + type: 'object', + children: { + b: { + type: 'any' + }, + a: { + type: 'alternatives', + alternatives: [ + { + ref: 'ref:b', + is: { + type: 'number', + flags: { + allowOnly: true, + presence: 'required' + }, + valids: [5], + invalids: [Infinity, -Infinity] + }, + then: { + type: 'string', + flags: { + allowOnly: true + }, + valids: ['x'], + invalids: [''] + }, + otherwise: { + type: 'string', + flags: { + allowOnly: true + }, + valids: ['y'], + invalids: [''] + } + }, + { + type: 'string', + flags: { + allowOnly: true + }, + valids: ['z'], + invalids: [''] + } + ] + } + } + }; + + expect(Joi.describe(schema)).to.deep.equal(outcome); + done(); + }); + + it('describes when (only then)', function (done) { + + var schema = { + a: Joi.alternatives().when('b', { is: 5, then: 'x' }) + .try('z'), + b: Joi.any() + }; + + var outcome = { + type: 'object', + children: { + b: { + type: 'any' + }, + a: { + type: 'alternatives', + alternatives: [ + { + ref: 'ref:b', + is: { + type: 'number', + flags: { + allowOnly: true, + presence: 'required' + }, + valids: [5], + invalids: [Infinity, -Infinity] + }, + then: { + type: 'string', + flags: { + allowOnly: true + }, + valids: ['x'], + invalids: [''] + } + }, + { + type: 'string', + flags: { + allowOnly: true + }, + valids: ['z'], + invalids: [''] + } + ] + } + } + }; + + expect(Joi.describe(schema)).to.deep.equal(outcome); + done(); + }); + + it('describes when (only otherwise)', function (done) { + + var schema = { + a: Joi.alternatives().when('b', { is: 5, otherwise: 'y' }) + .try('z'), + b: Joi.any() + }; + + var outcome = { + type: 'object', + children: { + b: { + type: 'any' + }, + a: { + type: 'alternatives', + alternatives: [ + { + ref: 'ref:b', + is: { + type: 'number', + flags: { + allowOnly: true, + presence: 'required' + }, + valids: [5], + invalids: [Infinity, -Infinity] + }, + otherwise: { + type: 'string', + flags: { + allowOnly: true + }, + valids: ['y'], + invalids: [''] + } + }, + { + type: 'string', + flags: { + allowOnly: true + }, + valids: ['z'], + invalids: [''] + } + ] + } + } + }; + + expect(Joi.describe(schema)).to.deep.equal(outcome); + done(); + }); + + it('describes inherited fields (from any)', function (done) { + + var schema = Joi.alternatives() + .try('a') + .description('d') + .example('a') + .meta('b') + .meta('c') + .notes('f') + .tags('g'); + + var outcome = { + type: 'alternatives', + description: 'd', + notes: ['f'], + tags: ['g'], + meta: ['b', 'c'], + examples: ['a'], + alternatives: [{ + type: 'string', + flags: { + allowOnly: true + }, + valids: ['a'], + invalids: [''] + }] + }; + + expect(Joi.describe(schema)).to.deep.equal(outcome); + done(); + }); + }); +});
@@ -0,0 +1,1595 @@
+// Load modules + +var Lab = require('lab'); +var Code = require('code'); +var Joi = require('../lib'); +var Helper = require('./helper'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +describe('any', function () { + + describe('#equal', function () { + + it('validates valid values', function (done) { + + Helper.validate(Joi.equal(4), [ + [4, true], + [5, false] + ], done); + }); + }); + + describe('#not', function () { + + it('validates invalid values', function (done) { + + Helper.validate(Joi.not(5), [ + [4, true], + [5, false] + ], done); + }); + }); + + describe('#exist', function () { + + it('validates required values', function (done) { + + Helper.validate(Joi.exist(), [ + [4, true], + [undefined, false] + ], done); + }); + }); + + describe('#strict', function () { + + it('validates without converting', function (done) { + + var schema = Joi.object({ + array: Joi.array().items(Joi.string().min(5), Joi.number().min(3)) + }).strict(); + + Helper.validate(schema, [ + [{ array: ['12345'] }, true], + [{ array: ['1'] }, false], + [{ array: [3] }, true], + [{ array: ['12345', 3] }, true], + [{ array: ['3'] }, false], + [{ array: [1] }, false] + ], done); + }); + + it('can be disabled', function (done) { + + var schema = Joi.object({ + array: Joi.array().items(Joi.string().min(5), Joi.number().min(3)) + }).strict().strict(false); + + Helper.validate(schema, [ + [{ array: ['12345'] }, true], + [{ array: ['1'] }, false], + [{ array: [3] }, true], + [{ array: ['12345', 3] }, true], + [{ array: ['3'] }, true], + [{ array: [1] }, false] + ], done); + }); + }); + + describe('#options', function () { + + it('adds to existing options', function (done) { + + var schema = Joi.object({ b: Joi.number().strict().options({ convert: true }) }); + var input = { b: '2' }; + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value.b).to.equal(2); + done(); + }); + }); + + it('throws with an invalid option', function (done) { + + expect(function () { + + Joi.any().options({ foo: 'bar' }); + }).to.throw('unknown key foo'); + done(); + }); + + it('throws with an invalid option type', function (done) { + + expect(function () { + + Joi.any().options({ convert: 'yes' }); + }).to.throw('convert should be of type boolean'); + done(); + }); + + it('throws with an invalid option value', function (done) { + + expect(function () { + + Joi.any().options({ presence: 'yes' }); + }).to.throw('presence should be one of required, optional, forbidden, ignore'); + done(); + }); + + it('does not throw with multiple options including presence key', function (done) { + + expect(function () { + + Joi.any().options({ presence: 'optional', raw: true }); + }).to.not.throw(); + done(); + }); + }); + + describe('#label', function () { + + it('adds to existing options', function (done) { + + var schema = Joi.object({ b: Joi.string().email().label('Custom label') }); + var input = { b: 'not_a_valid_email' }; + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.details[0].message).to.equal('"Custom label" must be a valid email'); + done(); + }); + }); + + it('throws when label is missing', function (done) { + + expect(function () { + + Joi.label(); + }).to.throw('Label name must be a non-empty string'); + done(); + }); + + it('can describe a label', function (done) { + + var schema = Joi.object().label('lbl').describe(); + expect(schema).to.deep.equal({ type: 'object', label: 'lbl' }); + done(); + }); + }); + + describe('#strict', function () { + + it('adds to existing options', function (done) { + + var schema = Joi.object({ b: Joi.number().options({ convert: true }).strict() }); + var input = { b: '2' }; + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(value.b).to.equal('2'); + done(); + }); + }); + }); + + describe('#raw', function () { + + it('gives the raw input', function (done) { + + var tests = [ + [Joi.array(), '[1,2,3]'], + [Joi.binary(), 'abc'], + [Joi.boolean(), 'false'], + [Joi.date().format('YYYYMMDD'), '19700101'], + [Joi.number(), '12'], + [Joi.object(), '{ "a": 1 }'], + [Joi.any().strict(), 'abc'] + ]; + + tests.forEach(function (test) { + + var baseSchema = test[0]; + var input = test[1]; + var schemas = [ + baseSchema.raw(), + baseSchema.raw(true), + baseSchema.options({ raw: true }) + ]; + + schemas.forEach(function (schema) { + + schema.raw().validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.equal(input); + }); + }); + }); + + done(); + }); + }); + + describe('#default', function () { + + it('sets the value', function (done) { + + var schema = Joi.object({ foo: Joi.string().default('test') }); + var input = {}; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value.foo).to.equal('test'); + done(); + }); + }); + + it('throws when value is a method and no description is provided', function (done) { + + expect(function () { + + Joi.object({ + foo: Joi.string().default(function () { + + return 'test'; + + }) + }); + }).to.throw(); + + done(); + }); + + it('allows passing description as a property of a default method', function (done) { + + var defaultFn = function () { + + return 'test'; + }; + defaultFn.description = 'test'; + + expect(function () { + + Joi.object({ foo: Joi.string().default(defaultFn) }); + }).to.not.throw(); + + done(); + }); + + it('sets the value when passing a method', function (done) { + + var schema = Joi.object({ + foo: Joi.string().default(function () { + + return 'test'; + }, 'testing') + }); + var input = {}; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value.foo).to.equal('test'); + done(); + }); + }); + + it('executes the default method each time validate is called', function (done) { + + var count = 0; + var schema = Joi.object({ + foo: Joi.number().default(function () { + + return ++count; + }, 'incrementer') + }); + var input = {}; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value.foo).to.equal(1); + }); + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value.foo).to.equal(2); + }); + + done(); + }); + + it('passes a clone of the context if the default method accepts an argument', function (done) { + + var schema = Joi.object({ + foo: Joi.string().default(function (context) { + + return context.bar + 'ing'; + }, 'testing'), + bar: Joi.string() + }); + var input = { bar: 'test' }; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value.foo).to.equal('testing'); + done(); + }); + }); + + it('does not modify the original object when modifying the clone in a default method', function (done) { + + var defaultFn = function (context) { + + context.bar = 'broken'; + return 'test'; + }; + defaultFn.description = 'testing'; + + var schema = Joi.object({ + foo: Joi.string().default(defaultFn), + bar: Joi.string() + }); + var input = { bar: 'test' }; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value.bar).to.equal('test'); + expect(value.foo).to.equal('test'); + done(); + }); + }); + + it('passes undefined as the context if the default method has no parent', function (done) { + + var c; + var methodCalled = false; + var schema = Joi.string().default(function (context) { + + methodCalled = true; + c = context; + return 'test'; + }, 'testing'); + + schema.validate(undefined, function (err, value) { + + expect(err).to.not.exist(); + expect(methodCalled).to.equal(true); + expect(c).to.equal(undefined); + expect(value).to.equal('test'); + done(); + }); + }); + + it('allows passing a method with no description to default when the object being validated is a function', function (done) { + + var defaultFn = function () { + + return 'just a function'; + }; + + var schema; + expect(function () { + + schema = Joi.func().default(defaultFn); + }).to.not.throw(); + + schema.validate(undefined, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(defaultFn); + done(); + }); + }); + + it('allows passing a method that generates a default method when validating a function', function (done) { + + var defaultFn = function () { + + return 'just a function'; + }; + + var defaultGeneratorFn = function () { + + return defaultFn; + }; + defaultGeneratorFn.description = 'generate a default fn'; + + var schema; + expect(function () { + + schema = Joi.func().default(defaultGeneratorFn); + }).to.not.throw(); + + schema.validate(undefined, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(defaultFn); + done(); + }); + }); + + it('allows passing a ref as a default without a description', function (done) { + + var schema = Joi.object({ + a: Joi.string(), + b: Joi.string().default(Joi.ref('a')) + }); + + schema.validate({ a: 'test' }, function (err, value) { + + expect(err).to.not.exist(); + expect(value.a).to.equal('test'); + expect(value.b).to.equal('test'); + done(); + }); + }); + + it('ignores description when passing a ref as a default', function (done) { + + var schema = Joi.object({ + a: Joi.string(), + b: Joi.string().default(Joi.ref('a'), 'this is a ref') + }); + + schema.validate({ a: 'test' }, function (err, value) { + + expect(err).to.not.exist(); + expect(value.a).to.equal('test'); + expect(value.b).to.equal('test'); + done(); + }); + }); + + it('catches errors in default methods', function (done) { + + var defaultFn = function () { + + throw new Error('boom'); + }; + defaultFn.description = 'broken method'; + + var schema = Joi.string().default(defaultFn); + + schema.validate(undefined, function (err, value) { + + expect(err).to.exist(); + expect(err.details).to.have.length(1); + expect(err.details[0].message).to.contain('threw an error when running default method'); + expect(err.details[0].type).to.equal('any.default'); + expect(err.details[0].context).to.be.an.instanceof(Error); + expect(err.details[0].context.message).to.equal('boom'); + done(); + }); + }); + + it('should not overide a value when value is given', function (done) { + + var schema = Joi.object({ foo: Joi.string().default('bar') }); + var input = { foo: 'test' }; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value.foo).to.equal('test'); + done(); + }); + }); + + it('sets value based on condition (outer)', function (done) { + + var schema = Joi.object({ + a: Joi.boolean(), + b: Joi.boolean().default(false).when('a', { is: true, then: Joi.required(), otherwise: Joi.forbidden() }) + }); + + schema.validate({ a: false }, function (err, value) { + + expect(err).to.not.exist(); + expect(value.b).to.equal(false); + done(); + }); + }); + + it('sets value based on condition (inner)', function (done) { + + var schema = Joi.object({ + a: Joi.boolean(), + b: Joi.boolean().when('a', { is: true, then: Joi.default(false), otherwise: Joi.forbidden() }) + }); + + schema.validate({ a: true }, function (err, value) { + + expect(err).to.not.exist(); + expect(value.b).to.equal(false); + done(); + }); + }); + + it('creates deep defaults', function (done) { + + var schema = Joi.object({ + a: Joi.number().default(42), + b: Joi.object({ + c: Joi.boolean().default(true), + d: Joi.string() + }).default() + }).default(); + + Helper.validate(schema, [ + [undefined, true, null, { a: 42, b: { c: true } }], + [{ a: 24 }, true, null, { a: 24, b: { c: true } }] + ], done); + }); + + it('should not affect objects other than object when called without an argument', function (done) { + + var schema = Joi.object({ + a: Joi.number().default() + }).default(); + + Helper.validate(schema, [ + [undefined, true, null, {}], + [{ a: 24 }, true, null, { a: 24 }] + ], done); + }); + + it('should set default value as a clone', function (done) { + + var defaultValue = { bar: 'val' }; + var schema = Joi.object({ foo: Joi.object().default(defaultValue) }); + var input = {}; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value.foo).to.not.equal(defaultValue); + expect(value.foo).to.only.deep.include({ bar: 'val' }); + + value.foo.bar = 'mutated'; + + schema.validate(input, function (err2, value2) { + + expect(err2).to.not.exist(); + expect(value2.foo).to.not.equal(defaultValue); + expect(value2.foo).to.only.deep.include({ bar: 'val' }); + + done(); + }); + }); + }); + + it('should not apply default values if the noDefaults option is enquire', function (done) { + + var schema = Joi.object({ + a: Joi.string().default('foo'), + b: Joi.number() + }); + + var input = { b: 42 }; + + Joi.validate(input, schema, { noDefaults: true }, function (err, value) { + + expect(err).to.not.exist(); + expect(value.a).to.not.exist(); + expect(value.b).to.be.equal(42); + + done(); + }); + }); + + it('should not apply default values from functions if the noDefaults option is enquire', function (done) { + + var func = function (context) { + + return 'foo'; + }; + + func.description = 'test parameter'; + + var schema = Joi.object({ + a: Joi.string().default(func), + b: Joi.number() + }); + + var input = { b: 42 }; + + Joi.validate(input, schema, { noDefaults: true }, function (err, value) { + + expect(err).to.not.exist(); + expect(value.a).to.not.exist(); + expect(value.b).to.be.equal(42); + + done(); + }); + }); + + it('should not apply default values from references if the noDefaults option is enquire', function (done) { + + var schema = Joi.object({ + a: Joi.string().default(Joi.ref('b')), + b: Joi.number() + }); + + var input = { b: 42 }; + + Joi.validate(input, schema, { noDefaults: true }, function (err, value) { + + expect(err).to.not.exist(); + expect(value.a).to.not.exist(); + expect(value.b).to.be.equal(42); + + done(); + }); + }); + }); + + describe('#optional', function () { + + it('validates optional with default required', function (done) { + + var schema = Joi.object({ + a: Joi.any(), + b: Joi.any(), + c: { + d: Joi.any() + } + }).options({ presence: 'required' }); + + Helper.validate(schema, [ + [{ a: 5 }, false], + [{ a: 5, b: 6 }, false], + [{ a: 5, b: 6, c: {} }, false], + [{ a: 5, b: 6, c: { d: 7 } }, true], + [{}, false], + [{ b: 5 }, false] + ], done); + }); + }); + + describe('#forbidden', function () { + + it('validates forbidden', function (done) { + + var schema = { + a: Joi.number(), + b: Joi.forbidden() + }; + + Helper.validate(schema, [ + [{ a: 5 }, true], + [{ a: 5, b: 6 }, false], + [{ a: 'a' }, false], + [{}, true], + [{ b: undefined }, true], + [{ b: null }, false] + ], done); + }); + }); + + describe('#strip', function () { + + it('validates and returns undefined', function (done) { + + var schema = Joi.string().strip(); + + schema.validate('test', function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.not.exist(); + done(); + }); + }); + + it('validates and returns an error', function (done) { + + var schema = Joi.string().strip(); + + schema.validate(1, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" must be a string'); + done(); + }); + }); + }); + + describe('#description', function () { + + it('sets the description', function (done) { + + var b = Joi.description('my description'); + expect(b._description).to.equal('my description'); + done(); + }); + + it('throws when description is missing', function (done) { + + expect(function () { + + Joi.description(); + }).to.throw('Description must be a non-empty string'); + done(); + }); + }); + + describe('#notes', function () { + + it('sets the notes', function (done) { + + var b = Joi.notes(['a']).notes('my notes'); + expect(b._notes).to.deep.equal(['a', 'my notes']); + done(); + }); + + it('throws when notes are missing', function (done) { + + expect(function () { + + Joi.notes(); + }).to.throw('Notes must be a non-empty string or array'); + done(); + }); + + it('throws when notes are invalid', function (done) { + + expect(function () { + + Joi.notes(5); + }).to.throw('Notes must be a non-empty string or array'); + done(); + }); + }); + + describe('#tags', function () { + + it('sets the tags', function (done) { + + var b = Joi.tags(['tag1', 'tag2']).tags('tag3'); + expect(b._tags).to.include('tag1'); + expect(b._tags).to.include('tag2'); + expect(b._tags).to.include('tag3'); + done(); + }); + + it('throws when tags are missing', function (done) { + + expect(function () { + + Joi.tags(); + }).to.throw('Tags must be a non-empty string or array'); + done(); + }); + + it('throws when tags are invalid', function (done) { + + expect(function () { + + Joi.tags(5); + }).to.throw('Tags must be a non-empty string or array'); + done(); + }); + }); + + describe('#meta', function () { + + it('sets the meta', function (done) { + + var meta = { prop: 'val', prop2: 3 }; + var b = Joi.meta(meta); + expect(b.describe().meta).to.deep.equal([meta]); + + b = b.meta({ other: true }); + expect(b.describe().meta).to.deep.equal([meta, { + other: true + }]); + + done(); + }); + + it('throws when meta is missing', function (done) { + + expect(function () { + + Joi.meta(); + }).to.throw('Meta cannot be undefined'); + done(); + }); + }); + + describe('#example', function () { + + it('sets an example', function (done) { + + var schema = Joi.valid(5, 6, 7).example(5); + expect(schema._examples).to.include(5); + expect(schema.describe().examples).to.deep.equal([5]); + done(); + }); + + it('throws when tags are missing', function (done) { + + expect(function () { + + Joi.example(); + }).to.throw('Missing example'); + done(); + }); + + it('throws when example fails own rules', function (done) { + + expect(function () { + + Joi.valid(5, 6, 7).example(4); + }).to.throw('Bad example: "value" must be one of [5, 6, 7]'); + done(); + }); + }); + + describe('#unit', function () { + + it('sets the unit', function (done) { + + var b = Joi.unit('milliseconds'); + expect(b._unit).to.equal('milliseconds'); + expect(b.describe().unit).to.equal('milliseconds'); + done(); + }); + + it('throws when unit is missing', function (done) { + + expect(function () { + + Joi.unit(); + }).to.throw('Unit name must be a non-empty string'); + done(); + }); + }); + + describe('#_validate', function () { + + it('checks value after conversion', function (done) { + + var schema = Joi.number().invalid(2); + Joi.validate('2', schema, { abortEarly: false }, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + }); + + describe('#concat', function () { + + it('throws when schema is not any', function (done) { + + expect(function () { + + Joi.string().concat(Joi.number()); + }).to.throw('Cannot merge type string with another type: number'); + done(); + }); + + it('throws when schema is missing', function (done) { + + expect(function () { + + Joi.string().concat(); + }).to.throw('Invalid schema object'); + done(); + }); + + it('throws when schema is invalid', function (done) { + + expect(function () { + + Joi.string().concat(1); + }).to.throw('Invalid schema object'); + done(); + }); + + it('merges two schemas (settings)', function (done) { + + var a = Joi.number().options({ convert: true }); + var b = Joi.options({ convert: false }); + + Helper.validate(a, [ + [1, true], ['1', true] + ]); + + Helper.validate(a.concat(b), [ + [1, true], ['1', false] + ], done); + }); + + it('merges two schemas (valid)', function (done) { + + var a = Joi.string().valid('a'); + var b = Joi.string().valid('b'); + + Helper.validate(a, [ + ['a', true], + ['b', false] + ]); + + Helper.validate(b, [ + ['b', true], + ['a', false] + ]); + + Helper.validate(a.concat(b), [ + ['a', true], + ['b', true] + ], done); + }); + + it('merges two schemas (invalid)', function (done) { + + var a = Joi.string().invalid('a'); + var b = Joi.invalid('b'); + + Helper.validate(a, [ + ['b', true], ['a', false] + ]); + + Helper.validate(b, [ + ['a', true], ['b', false] + ]); + + Helper.validate(a.concat(b), [ + ['a', false], ['b', false] + ], done); + }); + + it('merges two schemas (valid/invalid)', function (done) { + + var a = Joi.string().valid('a').invalid('b'); + var b = Joi.string().valid('b').invalid('a'); + + Helper.validate(a, [ + ['a', true], + ['b', false] + ]); + + Helper.validate(b, [ + ['b', true], + ['a', false] + ]); + + Helper.validate(a.concat(b), [ + ['a', false], + ['b', true] + ], done); + }); + + it('merges two schemas (tests)', function (done) { + + var a = Joi.number().min(5); + var b = Joi.number().max(10); + + Helper.validate(a, [ + [4, false], [11, true] + ]); + + Helper.validate(b, [ + [6, true], [11, false] + ]); + + Helper.validate(a.concat(b), [ + [4, false], [6, true], [11, false] + ], done); + }); + + it('merges two schemas (flags)', function (done) { + + var a = Joi.string().valid('a'); + var b = Joi.string().insensitive(); + + Helper.validate(a, [ + ['a', true], ['A', false], ['b', false] + ]); + + Helper.validate(a.concat(b), [ + ['a', true], ['A', true], ['b', false] + ], done); + }); + + it('overrides and append information', function (done) { + + var a = Joi.description('a').unit('a').tags('a').example('a'); + var b = Joi.description('b').unit('b').tags('b').example('b'); + + var desc = a.concat(b).describe(); + expect(desc).to.deep.equal({ + type: 'any', + description: 'b', + tags: ['a', 'b'], + examples: ['a', 'b'], + unit: 'b' + }); + done(); + }); + + it('merges two objects (any key + specific key)', function (done) { + + var a = Joi.object(); + var b = Joi.object({ b: 1 }); + + Helper.validate(a, [ + [{ b: 1 }, true], [{ b: 2 }, true] + ]); + + Helper.validate(b, [ + [{ b: 1 }, true], [{ b: 2 }, false] + ]); + + Helper.validate(a.concat(b), [ + [{ b: 1 }, true], [{ b: 2 }, false] + ]); + + Helper.validate(b.concat(a), [ + [{ b: 1 }, true], [{ b: 2 }, false] + ], done); + }); + + it('merges two objects (no key + any key)', function (done) { + + var a = Joi.object({}); + var b = Joi.object(); + + Helper.validate(a, [ + [{}, true], [{ b: 2 }, false] + ]); + + Helper.validate(b, [ + [{}, true], [{ b: 2 }, true] + ]); + + Helper.validate(a.concat(b), [ + [{}, true], [{ b: 2 }, false] + ]); + + Helper.validate(b.concat(a), [ + [{}, true], [{ b: 2 }, false] + ], done); + }); + + it('merges two objects (key + key)', function (done) { + + var a = Joi.object({ a: 1 }); + var b = Joi.object({ b: 2 }); + + Helper.validate(a, [ + [{ a: 1 }, true], [{ b: 2 }, false] + ]); + + Helper.validate(b, [ + [{ a: 1 }, false], [{ b: 2 }, true] + ]); + + Helper.validate(a.concat(b), [ + [{ a: 1 }, true], [{ b: 2 }, true] + ]); + + Helper.validate(b.concat(a), [ + [{ a: 1 }, true], [{ b: 2 }, true] + ], done); + }); + + it('merges two objects (renames)', function (done) { + + var a = Joi.object({ a: 1 }).rename('c', 'a'); + var b = Joi.object({ b: 2 }).rename('d', 'b'); + + a.concat(b).validate({ c: 1, d: 2 }, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal({ a: 1, b: 2 }); + done(); + }); + }); + + it('merges two objects (deps)', function (done) { + + var a = Joi.object({ a: 1 }); + var b = Joi.object({ b: 2 }).and('b', 'a'); + + a.concat(b).validate({ a: 1, b: 2 }, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('merges two objects (same key)', function (done) { + + var a = Joi.object({ a: 1, b: 2, c: 3 }); + var b = Joi.object({ b: 1, c: 2, a: 3 }); + + var ab = a.concat(b); + + Helper.validate(a, [ + [{ a: 1, b: 2, c: 3 }, true], + [{ a: 3, b: 1, c: 2 }, false] + ]); + + Helper.validate(b, [ + [{ a: 1, b: 2, c: 3 }, false], + [{ a: 3, b: 1, c: 2 }, true] + ]); + + Helper.validate(ab, [ + [{ a: 1, b: 2, c: 3 }, true], + [{ a: 3, b: 1, c: 2 }, true], + [{ a: 1, b: 2, c: 2 }, true], + [{ a: 1, b: 2, c: 4 }, false] + ], done); + }); + + it('throws when schema key types do not match', function (done) { + + var a = Joi.object({ a: Joi.number() }); + var b = Joi.object({ a: Joi.string() }); + + expect(function () { + + a.concat(b); + }).to.throw('Cannot merge type number with another type: string'); + done(); + }); + + it('merges two alternatives with references', function (done) { + + var schema = { + a: { c: Joi.number() }, + b: Joi.alternatives(Joi.ref('a.c')).concat(Joi.alternatives(Joi.ref('c'))), + c: Joi.number() + }; + + Helper.validate(schema, [ + [{ a: {} }, true], + [{ a: { c: '5' }, b: 5 }, true], + [{ a: { c: '5' }, b: 6, c: '6' }, true], + [{ a: { c: '5' }, b: 7, c: '6' }, false] + ], done); + }); + + it('merges meta properly', function (done) { + + var metaA = { a: 1 }; + var metaB = { b: 1 }; + var a = Joi.any().meta(metaA); + var b = Joi.any().meta(metaB); + var c = Joi.any(); + var d = Joi.any(); + + expect(a.concat(b)._meta).to.deep.equal([{ a: 1 }, { b: 1 }]); + expect(a.concat(c)._meta).to.deep.equal([metaA]); + expect(b.concat(c)._meta).to.deep.equal([metaB]); + expect(c.concat(d)._meta).to.deep.equal([]); + + done(); + }); + + it('merges into an any', function (done) { + + var a = Joi.any().required(); + var b = Joi.number().only(0); + + expect(function () { + + a.concat(b); + }).to.not.throw(); + + var schema = a.concat(b); + expect(schema.validate().error.message).to.equal('"value" is required'); + expect(schema.validate(1).error.message).to.equal('"value" must be one of [0]'); + + done(); + }); + }); + + describe('#when', function () { + + it('throws when options are invalid', function (done) { + + expect(function () { + + Joi.when('a'); + }).to.throw('Invalid options'); + done(); + }); + + it('forks type into alternatives', function (done) { + + var schema = { + a: Joi.any(), + b: Joi.string().valid('x').when('a', { is: 5, then: Joi.valid('y'), otherwise: Joi.valid('z') }) + }; + + Helper.validate(schema, [ + [{ a: 5, b: 'x' }, true], + [{ a: 5, b: 'y' }, true], + [{ a: 5, b: 'z' }, false], + [{ a: 1, b: 'x' }, true], + [{ a: 1, b: 'y' }, false], + [{ a: 1, b: 'z' }, true], + [{ a: 5, b: 'a' }, false], + [{ b: 'a' }, false] + ], done); + }); + + it('forks type into alternatives (only then)', function (done) { + + var schema = { + a: Joi.any(), + b: Joi.string().valid('x').when('a', { is: 5, then: Joi.valid('y') }) + }; + + Helper.validate(schema, [ + [{ a: 5, b: 'x' }, true], + [{ a: 5, b: 'y' }, true], + [{ a: 5, b: 'z' }, false], + [{ a: 1, b: 'x' }, true], + [{ a: 1, b: 'y' }, false], + [{ a: 1, b: 'z' }, false], + [{ a: 5, b: 'a' }, false], + [{ b: 'a' }, false] + ], done); + }); + + it('forks type into alternatives (only otherwise)', function (done) { + + var schema = { + a: Joi.any(), + b: Joi.string().valid('x').when('a', { is: 5, otherwise: Joi.valid('z') }) + }; + + Helper.validate(schema, [ + [{ a: 5, b: 'x' }, true], + [{ a: 5, b: 'y' }, false], + [{ a: 5, b: 'z' }, false], + [{ a: 1, b: 'x' }, true], + [{ a: 1, b: 'y' }, false], + [{ a: 1, b: 'z' }, true], + [{ a: 5, b: 'a' }, false], + [{ b: 'a' }, false] + ], done); + }); + + it('forks type into alternatives (with a schema)', function (done) { + + var schema = { + a: Joi.any(), + b: Joi.string().valid('x').when('a', { is: Joi.number().only(5).required(), then: Joi.valid('y') }) + }; + + Helper.validate(schema, [ + [{ a: 5, b: 'x' }, true], + [{ a: 5, b: 'y' }, true], + [{ a: 5, b: 'z' }, false], + [{ a: 1, b: 'x' }, true], + [{ a: 1, b: 'y' }, false], + [{ a: 1, b: 'z' }, false], + [{ a: 5, b: 'a' }, false], + [{ b: 'a' }, false] + ], done); + }); + + it('makes peer required', function (done) { + + var schema = { + a: Joi.when('b', { is: 5, then: Joi.required() }), + b: Joi.any() + }; + + Helper.validate(schema, [ + [{ b: 5 }, false], + [{ b: 6 }, true], + [{ a: 'b' }, true], + [{ b: 5, a: 'x' }, true] + ], done); + }); + }); + + describe('#requiredKeys', function () { + + it('should set keys as required', function (done) { + + var schema = Joi.object({ a: 0, b: 0, c: { d: 0, e: { f: 0 } }, g: { h: 0 } }) + .requiredKeys('a', 'b', 'c.d', 'c.e.f', 'g'); + Helper.validate(schema, [ + [{}, false], + [{ a: 0 }, false], + [{ a: 0, b: 0 }, false], + [{ a: 0, b: 0, g: {} }, true], + [{ a: 0, b: 0, c: {}, g: {} }, false], + [{ a: 0, b: 0, c: { d: 0 }, g: {} }, true], + [{ a: 0, b: 0, c: { d: 0, e: {} }, g: {} }, false], + [{ a: 0, b: 0, c: { d: 0, e: { f: 0 } }, g: {} }, true] + ], done); + }); + + it('should work on types other than objects', function (done) { + + var schemas = [Joi.array(), Joi.binary(), Joi.boolean(), Joi.date(), Joi.func(), Joi.number(), Joi.string()]; + schemas.forEach(function (schema) { + + expect(function () { + + schema.applyFunctionToChildren([''], 'required'); + }).to.not.throw(); + + expect(function () { + + schema.applyFunctionToChildren(['', 'a'], 'required'); + }).to.throw(); + + expect(function () { + + schema.applyFunctionToChildren(['a'], 'required'); + }).to.throw(); + }); + + done(); + }); + + it('should throw on unknown key', function (done) { + + expect(function () { + + Joi.object({ a: 0, b: 0 }).requiredKeys('a', 'c', 'b', 'd', 'd.e.f'); + }).to.throw(Error, 'unknown key(s) c, d'); + + expect(function () { + + Joi.object({ a: 0, b: 0 }).requiredKeys('a', 'b', 'a.c.d'); + }).to.throw(Error, 'unknown key(s) a.c.d'); + + done(); + }); + + it('should throw on empty object', function (done) { + + expect(function () { + + Joi.object().requiredKeys('a', 'c', 'b', 'd'); + }).to.throw(Error, 'unknown key(s) a, b, c, d'); + done(); + }); + + it('should not modify original object', function (done) { + + var schema = Joi.object({ a: 0 }); + var requiredSchema = schema.requiredKeys('a'); + schema.validate({}, function (err) { + + expect(err).to.not.exist(); + + requiredSchema.validate({}, function (err) { + + expect(err).to.exist(); + done(); + }); + }); + }); + }); + + describe('#optionalKeys', function () { + + it('should set keys as optional', function (done) { + + var schema = Joi.object({ a: Joi.number().required(), b: Joi.number().required() }).optionalKeys('a', 'b'); + Helper.validate(schema, [ + [{}, true], + [{ a: 0 }, true], + [{ a: 0, b: 0 }, true] + ], done); + }); + }); + + describe('#empty', function () { + + it('should void values when considered empty', function (done) { + + var schema = Joi.string().empty(''); + Helper.validate(schema, [ + [undefined, true, null, undefined], + ['abc', true, null, 'abc'], + ['', true, null, undefined] + ], done); + }); + + it('should override any previous empty', function (done) { + + var schema = Joi.string().empty('').empty('abc'); + Helper.validate(schema, [ + [undefined, true, null, undefined], + ['abc', true, null, undefined], + ['', false, null, '"value" is not allowed to be empty'], + ['def', true, null, 'def'] + ], done); + }); + + it('should be possible to reset the empty value', function (done) { + + var schema = Joi.string().empty('').empty(); + Helper.validate(schema, [ + [undefined, true, null, undefined], + ['abc', true, null, 'abc'], + ['', false, null, '"value" is not allowed to be empty'] + ], done); + }); + + it('should have no effect if only reset is used', function (done) { + + var schema = Joi.string().empty(); + Helper.validate(schema, [ + [undefined, true, null, undefined], + ['abc', true, null, 'abc'], + ['', false, null, '"value" is not allowed to be empty'] + ], done); + }); + + it('should work with dependencies', function (done) { + + var schema = Joi.object({ + a: Joi.string().empty(''), + b: Joi.string().empty('') + }).or('a', 'b'); + + Helper.validate(schema, [ + [{}, false, null, '"value" must contain at least one of [a, b]'], + [{ a: '' }, false, null, '"value" must contain at least one of [a, b]'], + [{ a: 'a' }, true, null, { a: 'a' }], + [{ a: '', b: 'b' }, true, null, { b: 'b' }] + ], done); + }); + }); + + describe('Set', function () { + + describe('#add', function () { + + it('throws when adding a non ref function', function (done) { + + expect(function () { + + Joi.valid(function () { }); + }).to.throw('Value cannot be an object or function'); + done(); + }); + + it('throws when adding an object function', function (done) { + + expect(function () { + + Joi.valid({}); + }).to.throw('Value cannot be an object or function'); + done(); + }); + }); + + describe('#has', function () { + + it('compares date to null', function (done) { + + var any = Joi.any().clone(); + any._valids.add(null); + expect(any._valids.has(new Date())).to.equal(false); + done(); + }); + + it('compares buffer to null', function (done) { + + var any = Joi.any().clone(); + any._valids.add(null); + expect(any._valids.has(new Buffer(''))).to.equal(false); + done(); + }); + }); + + describe('#values', function () { + + it('returns array', function (done) { + + var a = Joi.any().valid('x').invalid('y'); + var b = a.invalid('x'); + expect(a._valids.values().length).to.equal(1); + expect(b._valids.values().length).to.equal(0); + expect(a._invalids.values().length).to.equal(1); + expect(b._invalids.values().length).to.equal(2); + done(); + }); + + it('strips undefined', function (done) { + + var any = Joi.any().clone(); + any._valids.add(undefined); + expect(any._valids.values({ stripUndefined: true })).to.not.include(undefined); + done(); + }); + }); + + describe('#allow', function () { + + it('allows valid values to be set', function (done) { + + expect(function () { + + Joi.any().allow(true, 1, 'hello', new Date()); + }).not.to.throw(); + done(); + }); + + it('throws when passed undefined', function (done) { + + expect(function () { + + Joi.any().allow(undefined); + }).to.throw(Error, 'Cannot call allow/valid/invalid with undefined'); + done(); + }); + }); + + describe('#valid', function () { + + it('allows valid values to be set', function (done) { + + expect(function () { + + Joi.any().valid(true, 1, 'hello', new Date()); + }).not.to.throw(); + done(); + }); + + it('throws when passed undefined', function (done) { + + expect(function () { + + Joi.any().valid(undefined); + }).to.throw(Error, 'Cannot call allow/valid/invalid with undefined'); + done(); + }); + }); + + describe('#invalid', function () { + + it('allows invalid values to be set', function (done) { + + expect(function () { + + Joi.any().valid(true, 1, 'hello', new Date()); + }).not.to.throw(); + done(); + }); + + it('throws when passed undefined', function (done) { + + expect(function () { + + Joi.any().invalid(undefined); + }).to.throw('Cannot call allow/valid/invalid with undefined'); + done(); + }); + }); + }); +});
@@ -0,0 +1,1049 @@
+// Load modules + +var Lab = require('lab'); +var Code = require('code'); +var Joi = require('../lib'); +var Helper = require('./helper'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +describe('array', function () { + + it('converts a string to an array', function (done) { + + Joi.array().validate('[1,2,3]', function (err, value) { + + expect(err).to.not.exist(); + expect(value.length).to.equal(3); + done(); + }); + }); + + it('errors on non-array string', function (done) { + + Joi.array().validate('{ "something": false }', function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" must be an array'); + done(); + }); + }); + + it('errors on number', function (done) { + + Joi.array().validate(3, function (err, value) { + + expect(err).to.exist(); + expect(value).to.equal(3); + done(); + }); + }); + + it('converts a non-array string with number type', function (done) { + + Joi.array().validate('3', function (err, value) { + + expect(err).to.exist(); + expect(value).to.equal('3'); + done(); + }); + }); + + it('errors on a non-array string', function (done) { + + Joi.array().validate('asdf', function (err, value) { + + expect(err).to.exist(); + expect(value).to.equal('asdf'); + done(); + }); + }); + + describe('#items', function () { + + it('converts members', function (done) { + + var schema = Joi.array().items(Joi.number()); + var input = ['1', '2', '3']; + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal([1, 2, 3]); + done(); + }); + }); + + it('shows path to errors in array items', function (done) { + + expect(function () { + + Joi.array().items({ + a: { + b: { + c: { + d: undefined + } + } + } + }); + }).to.throw(Error, 'Invalid schema content: (0.a.b.c.d)'); + + expect(function () { + + Joi.array().items({ foo: 'bar' }, undefined); + }).to.throw(Error, 'Invalid schema content: (1)'); + + done(); + }); + + it('allows zero size', function (done) { + + var schema = Joi.object({ + test: Joi.array().items(Joi.object({ + foo: Joi.string().required() + })) + }); + var input = { test: [] }; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('returns the first error when only one inclusion', function (done) { + + var schema = Joi.object({ + test: Joi.array().items(Joi.object({ + foo: Joi.string().required() + })) + }); + var input = { test: [{ foo: 'a' }, { bar: 2 }] }; + + schema.validate(input, function (err, value) { + + expect(err.message).to.equal('child "test" fails because ["test" at position 1 fails because [child "foo" fails because ["foo" is required]]]'); + done(); + }); + }); + + it('validates multiple types added in two calls', function (done) { + + var schema = Joi.array() + .items(Joi.number()) + .items(Joi.string()); + + Helper.validate(schema, [ + [[1, 2, 3], true], + [[50, 100, 1000], true], + [[1, 'a', 5, 10], true], + [['joi', 'everydaylowprices', 5000], true] + ], done); + }); + + it('validates multiple types with stripUnknown', function (done) { + + var schema = Joi.array().items(Joi.number(), Joi.string()).options({ stripUnknown: true }); + + Helper.validate(schema, [ + [[1, 2, 'a'], true, null, [1, 2, 'a']], + [[1, { foo: 'bar' }, 'a', 2], true, null, [1, 'a', 2]] + ], done); + }); + + it('allows forbidden to restrict values', function (done) { + + var schema = Joi.array().items(Joi.string().valid('four').forbidden(), Joi.string()); + var input = ['one', 'two', 'three', 'four']; + + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" at position 3 contains an excluded value'); + done(); + }); + }); + + it('validates that a required value exists', function (done) { + + var schema = Joi.array().items(Joi.string().valid('four').required(), Joi.string()); + var input = ['one', 'two', 'three']; + + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" does not contain 1 required value(s)'); + done(); + }); + }); + + it('validates that a required value exists with abortEarly = false', function (done) { + + var schema = Joi.array().items(Joi.string().valid('four').required(), Joi.string()).options({ abortEarly: false }); + var input = ['one', 'two', 'three']; + + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" does not contain 1 required value(s)'); + done(); + }); + }); + + it('does not re-run required tests that have already been matched', function (done) { + + var schema = Joi.array().items(Joi.string().valid('four').required(), Joi.string()); + var input = ['one', 'two', 'three', 'four', 'four', 'four']; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(input); + done(); + }); + }); + + it('does not re-run required tests that have already failed', function (done) { + + var schema = Joi.array().items(Joi.string().valid('four').required(), Joi.boolean().required(), Joi.number()); + var input = ['one', 'two', 'three', 'four', 'four', 'four']; + + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" at position 0 does not match any of the allowed types'); + done(); + }); + }); + + it('can require duplicates of the same schema and fail', function (done) { + + var schema = Joi.array().items(Joi.string().valid('four').required(), Joi.string().valid('four').required(), Joi.string()); + var input = ['one', 'two', 'three', 'four']; + + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" does not contain 1 required value(s)'); + done(); + }); + }); + + it('can require duplicates of the same schema and pass', function (done) { + + var schema = Joi.array().items(Joi.string().valid('four').required(), Joi.string().valid('four').required(), Joi.string()); + var input = ['one', 'two', 'three', 'four', 'four']; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(input); + done(); + }); + }); + + it('continues to validate after a required match', function (done) { + + var schema = Joi.array().items(Joi.string().required(), Joi.boolean()); + var input = [true, 'one', false, 'two']; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(input); + done(); + }); + }); + + it('can use a label on a required parameter', function (done) { + + var schema = Joi.array().items(Joi.string().required().label('required string'), Joi.boolean()); + var input = [true, false]; + + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" does not contain [required string]'); + done(); + }); + }); + + it('can use a label on one required parameter, and no label on another', function (done) { + + var schema = Joi.array().items(Joi.string().required().label('required string'), Joi.string().required(), Joi.boolean()); + var input = [true, false]; + + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" does not contain [required string] and 1 other required value(s)'); + done(); + }); + }); + + it('can strip matching items', function (done) { + + var schema = Joi.array().items(Joi.string(), Joi.any().strip()); + schema.validate(['one', 'two', 3, 4], function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(['one', 'two']); + done(); + }); + }); + }); + + describe('#min', function () { + + it('validates array size', function (done) { + + var schema = Joi.array().min(2); + Helper.validate(schema, [ + [[1, 2], true], + [[1], false] + ], done); + }); + + it('throws when limit is not a number', function (done) { + + expect(function () { + + Joi.array().min('a'); + }).to.throw('limit must be a positive integer'); + done(); + }); + + it('throws when limit is not an integer', function (done) { + + expect(function () { + + Joi.array().min(1.2); + }).to.throw('limit must be a positive integer'); + done(); + }); + }); + + describe('#max', function () { + + it('validates array size', function (done) { + + var schema = Joi.array().max(1); + Helper.validate(schema, [ + [[1, 2], false], + [[1], true] + ], done); + }); + + it('throws when limit is not a number', function (done) { + + expect(function () { + + Joi.array().max('a'); + }).to.throw('limit must be a positive integer'); + done(); + }); + + it('throws when limit is not an integer', function (done) { + + expect(function () { + + Joi.array().max(1.2); + }).to.throw('limit must be a positive integer'); + done(); + }); + }); + + describe('#length', function () { + + it('validates array size', function (done) { + + var schema = Joi.array().length(2); + Helper.validate(schema, [ + [[1, 2], true], + [[1], false] + ], done); + }); + + it('throws when limit is not a number', function (done) { + + expect(function () { + + Joi.array().length('a'); + }).to.throw('limit must be a positive integer'); + done(); + }); + + it('throws when limit is not an integer', function (done) { + + expect(function () { + + Joi.array().length(1.2); + }).to.throw('limit must be a positive integer'); + done(); + }); + }); + + describe('#validate', function () { + + it('should, by default, allow undefined, allow empty array', function (done) { + + Helper.validate(Joi.array(), [ + [undefined, true], + [[], true] + ], done); + }); + + it('should, when .required(), deny undefined', function (done) { + + Helper.validate(Joi.array().required(), [ + [undefined, false] + ], done); + }); + + it('allows empty arrays', function (done) { + + Helper.validate(Joi.array(), [ + [undefined, true], + [[], true] + ], done); + }); + + it('excludes values when items are forbidden', function (done) { + + Helper.validate(Joi.array().items(Joi.string().forbidden()), [ + [['2', '1'], false], + [['1'], false], + [[2], true] + ], done); + }); + + it('allows types to be forbidden', function (done) { + + var schema = Joi.array().items(Joi.number().forbidden()); + + var n = [1, 2, 'hippo']; + schema.validate(n, function (err, value) { + + expect(err).to.exist(); + + var m = ['x', 'y', 'z']; + schema.validate(m, function (err2, value2) { + + expect(err2).to.not.exist(); + done(); + }); + }); + }); + + it('validates array of Numbers', function (done) { + + Helper.validate(Joi.array().items(Joi.number()), [ + [[1, 2, 3], true], + [[50, 100, 1000], true], + [['a', 1, 2], false], + [['1', '2', 4], true] + ], done); + }); + + it('validates array of mixed Numbers & Strings', function (done) { + + Helper.validate(Joi.array().items(Joi.number(), Joi.string()), [ + [[1, 2, 3], true], + [[50, 100, 1000], true], + [[1, 'a', 5, 10], true], + [['joi', 'everydaylowprices', 5000], true] + ], done); + }); + + it('validates array of objects with schema', function (done) { + + Helper.validate(Joi.array().items(Joi.object({ h1: Joi.number().required() })), [ + [[{ h1: 1 }, { h1: 2 }, { h1: 3 }], true], + [[{ h2: 1, h3: 'somestring' }, { h1: 2 }, { h1: 3 }], false], + [[1, 2, [1]], false] + ], done); + }); + + it('errors on array of unallowed mixed types (Array)', function (done) { + + Helper.validate(Joi.array().items(Joi.number()), [ + [[1, 2, 3], true], + [[1, 2, [1]], false] + ], done); + }); + + it('errors on invalid number rule using includes', function (done) { + + var schema = Joi.object({ + arr: Joi.array().items(Joi.number().integer()) + }); + + var input = { arr: [1, 2, 2.1] }; + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('child "arr" fails because ["arr" at position 2 fails because ["2" must be an integer]]'); + done(); + }); + }); + + it('validates an array within an object', function (done) { + + var schema = Joi.object({ + array: Joi.array().items(Joi.string().min(5), Joi.number().min(3)) + }).options({ convert: false }); + + Helper.validate(schema, [ + [{ array: ['12345'] }, true], + [{ array: ['1'] }, false], + [{ array: [3] }, true], + [{ array: ['12345', 3] }, true] + ], done); + }); + + it('should not change original value', function (done) { + + var schema = Joi.array().items(Joi.number()).unique(); + var input = ['1', '2']; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal([1, 2]); + expect(input).to.deep.equal(['1', '2']); + done(); + }); + }); + + it('should have multiple errors if abort early is false', function (done) { + + var schema = Joi.array().items(Joi.number(), Joi.object()).items(Joi.boolean().forbidden()); + var input = [1, undefined, true, 'a']; + + Joi.validate(input, schema, { abortEarly: false }, function (err, value) { + + expect(err).to.exist(); + expect(err).to.have.length(4); + expect(err.details).to.deep.equal([{ + message: '"value" must not be a sparse array', + path: '1', + type: 'array.sparse', + context: { + key: 'value' + } + }, { + message: '"value" at position 2 contains an excluded value', + path: '2', + type: 'array.excludes', + context: { + pos: 2, + key: 'value', + value: true + } + }, { + message: '"value" at position 3 does not match any of the allowed types', + path: '3', + type: 'array.includes', + context: { + pos: 3, + key: 'value', + value: 'a' + } + }]); + done(); + }); + }); + }); + + describe('#describe', function () { + + it('returns an empty description when no rules are applied', function (done) { + + var schema = Joi.array(); + var desc = schema.describe(); + expect(desc).to.deep.equal({ + type: 'array', + flags: { sparse: false } + }); + done(); + }); + + it('returns an updated description when sparse rule is applied', function (done) { + + var schema = Joi.array().sparse(); + var desc = schema.describe(); + expect(desc).to.deep.equal({ + type: 'array', + flags: { sparse: true } + }); + done(); + }); + + it('returns an items array only if items are specified', function (done) { + + var schema = Joi.array().items().max(5); + var desc = schema.describe(); + expect(desc.items).to.not.exist(); + done(); + }); + + it('returns a recursively defined array of items when specified', function (done) { + + var schema = Joi.array() + .items(Joi.number(), Joi.string()) + .items(Joi.boolean().forbidden()) + .ordered(Joi.number(), Joi.string()) + .ordered(Joi.string().required()); + var desc = schema.describe(); + expect(desc.items).to.have.length(3); + expect(desc).to.deep.equal({ + type: 'array', + flags: { sparse: false }, + orderedItems: [{ type: 'number', invalids: [Infinity, -Infinity] }, { type: 'string', invalids: [''] }, { type: 'string', invalids: [''], flags: { presence: 'required' } }], + items: [{ type: 'number', invalids: [Infinity, -Infinity] }, { type: 'string', invalids: [''] }, { type: 'boolean', flags: { presence: 'forbidden' } }] + }); + + done(); + }); + }); + + describe('#unique', function () { + + it('errors if duplicate numbers, strings, objects, binaries, functions, dates and booleans', function (done) { + + var buffer = new Buffer('hello world'); + var func = function () {}; + var now = new Date(); + var schema = Joi.array().sparse().unique(); + + Helper.validate(schema, [ + [[2, 2], false], + [[02, 2], false], // eslint-disable-line no-octal + [[0x2, 2], false], + [['duplicate', 'duplicate'], false], + [[{ a: 'b' }, { a: 'b' }], false], + [[buffer, buffer], false], + [[func, func], false], + [[now, now], false], + [[true, true], false], + [[undefined, undefined], false] + ], done); + }); + + it('ignores duplicates if they are of different types', function (done) { + + var schema = Joi.array().unique(); + + Helper.validate(schema, [ + [[2, '2'], true] + ], done); + }); + + it('validates without duplicates', function (done) { + + var buffer = new Buffer('hello world'); + var buffer2 = new Buffer('Hello world'); + var func = function () {}; + var func2 = function () {}; + var now = new Date(); + var now2 = new Date(+now + 100); + var schema = Joi.array().unique(); + + Helper.validate(schema, [ + [[1, 2], true], + [['s1', 's2'], true], + [[{ a: 'b' }, { a: 'c' }], true], + [[buffer, buffer2], true], + [[func, func2], true], + [[now, now2], true], + [[true, false], true] + ], done); + }); + }); + + describe('#sparse', function () { + + it('errors on undefined value', function (done) { + + var schema = Joi.array().items(Joi.number()); + + Helper.validate(schema, [ + [[undefined], false], + [[2, undefined], false] + ], done); + }); + + it('validates on undefined value with sparse', function (done) { + + var schema = Joi.array().items(Joi.number()).sparse(); + + Helper.validate(schema, [ + [[undefined], true], + [[2, undefined], true] + ], done); + }); + + it('switches the sparse flag', function (done) { + + var schema = Joi.array().sparse(); + var desc = schema.describe(); + expect(desc).to.deep.equal({ + type: 'array', + flags: { sparse: true } + }); + done(); + }); + + it('switches the sparse flag with explicit value', function (done) { + + var schema = Joi.array().sparse(true); + var desc = schema.describe(); + expect(desc).to.deep.equal({ + type: 'array', + flags: { sparse: true } + }); + done(); + }); + + it('switches the sparse flag back', function (done) { + + var schema = Joi.array().sparse().sparse(false); + var desc = schema.describe(); + expect(desc).to.deep.equal({ + type: 'array', + flags: { sparse: false } + }); + done(); + }); + }); + + describe('#single', function () { + + it('should allow a single element', function (done) { + + var schema = Joi.array().items(Joi.number()).items(Joi.boolean().forbidden()).single(); + + Helper.validate(schema, [ + [[1, 2, 3], true], + [1, true], + [['a'], false, null, '"value" at position 0 fails because ["0" must be a number]'], + ['a', false, null, 'single value of "value" fails because ["0" must be a number]'], + [true, false, null, 'single value of "value" contains an excluded value'] + ], done); + }); + + it('should allow a single element with multiple types', function (done) { + + var schema = Joi.array().items(Joi.number(), Joi.string()).single(); + + Helper.validate(schema, [ + [[1, 2, 3], true], + [1, true], + [[1, 'a'], true], + ['a', true], + [true, false, null, 'single value of "value" does not match any of the allowed types'] + ], done); + }); + + it('should allow nested arrays', function (done) { + + var schema = Joi.array().items(Joi.array().items(Joi.number())).single(); + + Helper.validate(schema, [ + [[[1], [2], [3]], true], + [[1, 2, 3], true], + [[['a']], false, null, '"value" at position 0 fails because ["0" at position 0 fails because ["0" must be a number]]'], + [['a'], false, null, '"value" at position 0 fails because ["0" must be an array]'], + ['a', false, null, 'single value of "value" fails because ["0" must be an array]'], + [1, false, null, 'single value of "value" fails because ["0" must be an array]'], + [true, false, null, 'single value of "value" fails because ["0" must be an array]'] + ], done); + }); + + it('should allow nested arrays with multiple types', function (done) { + + var schema = Joi.array().items(Joi.array().items(Joi.number(), Joi.boolean())).single(); + + Helper.validate(schema, [ + [[[1, true]], true], + [[1, true], true], + [[[1, 'a']], false, null, '"value" at position 0 fails because ["0" at position 1 does not match any of the allowed types]'], + [[1, 'a'], false, null, '"value" at position 0 fails because ["0" must be an array]'] + ], done); + }); + + it('switches the single flag with explicit value', function (done) { + + var schema = Joi.array().single(true); + var desc = schema.describe(); + expect(desc).to.deep.equal({ + type: 'array', + flags: { sparse: false, single: true } + }); + done(); + }); + + it('switches the single flag back', function (done) { + + var schema = Joi.array().single().single(false); + var desc = schema.describe(); + expect(desc).to.deep.equal({ + type: 'array', + flags: { sparse: false, single: false } + }); + done(); + }); + }); + + describe('#options', function () { + + it('respects stripUnknown', function (done) { + + var schema = Joi.array().items(Joi.string()).options({ stripUnknown: true }); + schema.validate(['one', 'two', 3, 4, true, false], function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(['one', 'two']); + done(); + }); + }); + }); + + describe('#ordered', function () { + + it('shows path to errors in array ordered items', function (done) { + + expect(function () { + + Joi.array().ordered({ + a: { + b: { + c: { + d: undefined + } + } + } + }); + }).to.throw(Error, 'Invalid schema content: (0.a.b.c.d)'); + + expect(function () { + + Joi.array().ordered({ foo: 'bar' }, undefined); + }).to.throw(Error, 'Invalid schema content: (1)'); + + done(); + }); + + it('validates input against items in order', function (done) { + + var schema = Joi.array().ordered([Joi.string().required(), Joi.number().required()]); + var input = ['s1', 2]; + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(['s1', 2]); + done(); + }); + }); + + it('validates input with optional item', function (done) { + + var schema = Joi.array().ordered([Joi.string().required(), Joi.number().required(), Joi.number()]); + var input = ['s1', 2, 3]; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(['s1', 2, 3]); + done(); + }); + }); + + it('validates input without optional item', function (done) { + + var schema = Joi.array().ordered([Joi.string().required(), Joi.number().required(), Joi.number()]); + var input = ['s1', 2]; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(['s1', 2]); + done(); + }); + }); + + it('validates input without optional item', function (done) { + + var schema = Joi.array().ordered([Joi.string().required(), Joi.number().required(), Joi.number()]).sparse(true); + var input = ['s1', 2, undefined]; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(['s1', 2, undefined]); + done(); + }); + }); + + it('validates input without optional item in a sparse array', function (done) { + + var schema = Joi.array().ordered([Joi.string().required(), Joi.number(), Joi.number().required()]).sparse(true); + var input = ['s1', undefined, 3]; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(['s1', undefined, 3]); + done(); + }); + }); + + it('validates when input matches ordered items and matches regular items', function (done) { + + var schema = Joi.array().ordered([Joi.string().required(), Joi.number().required()]).items(Joi.number()); + var input = ['s1', 2, 3, 4, 5]; + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(['s1', 2, 3, 4, 5]); + done(); + }); + }); + + it('errors when input does not match ordered items', function (done) { + + var schema = Joi.array().ordered([Joi.number().required(), Joi.string().required()]); + var input = ['s1', 2]; + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" at position 0 fails because ["0" must be a number]'); + done(); + }); + }); + + it('errors when input has more items than ordered items', function (done) { + + var schema = Joi.array().ordered([Joi.number().required(), Joi.string().required()]); + var input = [1, 's2', 3]; + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" at position 2 fails because array must contain at most 2 items'); + done(); + }); + }); + + it('errors when input has more items than ordered items with abortEarly = false', function (done) { + + var schema = Joi.array().ordered([Joi.string(), Joi.number()]).options({ abortEarly: false }); + var input = [1, 2, 3, 4, 5]; + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" at position 0 fails because ["0" must be a string]. "value" at position 2 fails because array must contain at most 2 items. "value" at position 3 fails because array must contain at most 2 items. "value" at position 4 fails because array must contain at most 2 items'); + expect(err.details).to.have.length(4); + done(); + }); + }); + + it('errors when input has less items than ordered items', function (done) { + + var schema = Joi.array().ordered([Joi.number().required(), Joi.string().required()]); + var input = [1]; + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" does not contain 1 required value(s)'); + done(); + }); + }); + + it('errors when input matches ordered items but not matches regular items', function (done) { + + var schema = Joi.array().ordered([Joi.string().required(), Joi.number().required()]).items(Joi.number()).options({ abortEarly: false }); + var input = ['s1', 2, 3, 4, 's5']; + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" at position 4 fails because ["4" must be a number]'); + done(); + }); + }); + + it('errors when input does not match ordered items but matches regular items', function (done) { + + var schema = Joi.array().ordered([Joi.string(), Joi.number()]).items(Joi.number()).options({ abortEarly: false }); + var input = [1, 2, 3, 4, 5]; + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" at position 0 fails because ["0" must be a string]'); + done(); + }); + }); + + it('errors when input does not match ordered items not matches regular items', function (done) { + + var schema = Joi.array().ordered([Joi.string(), Joi.number()]).items(Joi.string()).options({ abortEarly: false }); + var input = [1, 2, 3, 4, 5]; + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" at position 0 fails because ["0" must be a string]. "value" at position 2 fails because ["2" must be a string]. "value" at position 3 fails because ["3" must be a string]. "value" at position 4 fails because ["4" must be a string]'); + expect(err.details).to.have.length(4); + done(); + }); + }); + + it('errors but continues when abortEarly is set to false', function (done) { + + var schema = Joi.array().ordered([Joi.number().required(), Joi.string().required()]).options({ abortEarly: false }); + var input = ['s1', 2]; + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" at position 0 fails because ["0" must be a number]. "value" at position 1 fails because ["1" must be a string]'); + expect(err.details).to.have.length(2); + done(); + }); + }); + + it('strips item', function (done) { + + var schema = Joi.array().ordered([Joi.string().required(), Joi.number().strip(), Joi.number().required()]); + var input = ['s1', 2, 3]; + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(['s1', 3]); + done(); + }); + }); + + it('strips multiple items', function (done) { + + var schema = Joi.array().ordered([Joi.string().strip(), Joi.number(), Joi.number().strip()]); + var input = ['s1', 2, 3]; + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal([2]); + done(); + }); + }); + }); +});
@@ -0,0 +1,188 @@
+// Load modules + +var Lab = require('lab'); +var Code = require('code'); +var Joi = require('../lib'); +var Helper = require('./helper'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +describe('binary', function () { + + it('converts a string to a buffer', function (done) { + + Joi.binary().validate('test', function (err, value) { + + expect(err).to.not.exist(); + expect(value instanceof Buffer).to.equal(true); + expect(value.length).to.equal(4); + expect(value.toString('utf8')).to.equal('test'); + done(); + }); + }); + + it('validates allowed buffer content', function (done) { + + var hello = new Buffer('hello'); + var schema = Joi.binary().valid(hello); + + Helper.validate(schema, [ + ['hello', true], + [hello, true], + [new Buffer('hello'), true], + ['goodbye', false], + [new Buffer('goodbye'), false], + [new Buffer('HELLO'), false] + ], done); + }); + + describe('#validate', function () { + + it('returns an error when a non-buffer or non-string is used', function (done) { + + Joi.binary().validate(5, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" must be a buffer or a string'); + done(); + }); + }); + + it('accepts a buffer object', function (done) { + + Joi.binary().validate(new Buffer('hello world'), function (err, value) { + + expect(err).to.not.exist(); + expect(value.toString('utf8')).to.equal('hello world'); + done(); + }); + }); + }); + + describe('#encoding', function () { + + it('applies encoding', function (done) { + + var schema = Joi.binary().encoding('base64'); + var input = new Buffer('abcdef'); + schema.validate(input.toString('base64'), function (err, value) { + + expect(err).to.not.exist(); + expect(value instanceof Buffer).to.equal(true); + expect(value.toString()).to.equal('abcdef'); + done(); + }); + }); + + it('throws when encoding is invalid', function (done) { + + expect(function () { + + Joi.binary().encoding('base6'); + }).to.throw('Invalid encoding: base6'); + done(); + }); + }); + + describe('#min', function () { + + it('validates buffer size', function (done) { + + var schema = Joi.binary().min(5); + Helper.validate(schema, [ + [new Buffer('testing'), true], + [new Buffer('test'), false] + ], done); + }); + + it('throws when min is not a number', function (done) { + + expect(function () { + + Joi.binary().min('a'); + }).to.throw('limit must be a positive integer'); + done(); + }); + + it('throws when min is not an integer', function (done) { + + expect(function () { + + Joi.binary().min(1.2); + }).to.throw('limit must be a positive integer'); + done(); + }); + }); + + describe('#max', function () { + + it('validates buffer size', function (done) { + + var schema = Joi.binary().max(5); + Helper.validate(schema, [ + [new Buffer('testing'), false], + [new Buffer('test'), true] + ], done); + }); + + it('throws when max is not a number', function (done) { + + expect(function () { + + Joi.binary().max('a'); + }).to.throw('limit must be a positive integer'); + done(); + }); + + it('throws when max is not an integer', function (done) { + + expect(function () { + + Joi.binary().max(1.2); + }).to.throw('limit must be a positive integer'); + done(); + }); + }); + + describe('#length', function () { + + it('validates buffer size', function (done) { + + var schema = Joi.binary().length(4); + Helper.validate(schema, [ + [new Buffer('test'), true], + [new Buffer('testing'), false] + ], done); + }); + + it('throws when length is not a number', function (done) { + + expect(function () { + + Joi.binary().length('a'); + }).to.throw('limit must be a positive integer'); + done(); + }); + + it('throws when length is not an integer', function (done) { + + expect(function () { + + Joi.binary().length(1.2); + }).to.throw('limit must be a positive integer'); + done(); + }); + }); +});
@@ -0,0 +1,129 @@
+// Load modules + +var Lab = require('lab'); +var Code = require('code'); +var Joi = require('../lib'); +var Helper = require('./helper'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +describe('boolean', function () { + + it('converts a string to a boolean', function (done) { + + Joi.boolean().validate('true', function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.equal(true); + done(); + }); + }); + + it('errors on a number', function (done) { + + Joi.boolean().validate(1, function (err, value) { + + expect(err).to.exist(); + expect(value).to.equal(1); + done(); + }); + }); + + describe('#validate', function () { + + it('converts string values and validates', function (done) { + + var rule = Joi.boolean(); + Helper.validate(rule, [ + ['1234', false], + [false, true], + [true, true], + [null, false], + ['on', true], + ['off', true], + ['true', true], + ['false', true], + ['yes', true], + ['no', true] + ], done); + }); + + it('should handle work with required', function (done) { + + var rule = Joi.boolean().required(); + Helper.validate(rule, [ + ['1234', false], + ['true', true], + [false, true], + [true, true], + [null, false] + ], done); + }); + + it('should handle work with allow', function (done) { + + var rule = Joi.boolean().allow(false); + Helper.validate(rule, [ + ['1234', false], + [false, true], + [null, false] + ], done); + }); + + it('should handle work with invalid', function (done) { + + var rule = Joi.boolean().invalid(false); + Helper.validate(rule, [ + ['1234', false], + [false, false], + [true, true], + [null, false] + ], done); + }); + + it('should handle work with invalid and null allowed', function (done) { + + var rule = Joi.boolean().invalid(false).allow(null); + Helper.validate(rule, [ + ['1234', false], + [false, false], + [true, true], + [null, true] + ], done); + }); + + it('should handle work with allow and invalid', function (done) { + + var rule = Joi.boolean().invalid(true).allow(false); + Helper.validate(rule, [ + ['1234', false], + [false, true], + [true, false], + [null, false] + ], done); + }); + + it('should handle work with allow, invalid, and null allowed', function (done) { + + var rule = Joi.boolean().invalid(true).allow(false).allow(null); + Helper.validate(rule, [ + ['1234', false], + [false, true], + [true, false], + [null, true] + ], done); + }); + }); +});
@@ -0,0 +1,338 @@
+// Load modules + +var Lab = require('lab'); +var Code = require('code'); +var Joi = require('../lib'); +var Helper = require('./helper'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +describe('date', function () { + + it('fails on boolean', function (done) { + + var schema = Joi.date(); + Helper.validate(schema, [ + [true, false], + [false, false] + ], done); + }); + + it('matches specific date', function (done) { + + var now = Date.now(); + Joi.date().valid(new Date(now)).validate(new Date(now), function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('errors on invalid input and convert disabled', function (done) { + + Joi.date().options({ convert: false }).validate('1-1-2013 UTC', function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" must be a number of milliseconds or valid date string'); + done(); + }); + }); + + it('validates date', function (done) { + + Joi.date().validate(new Date(), function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('validates millisecond date as a string', function (done) { + + var now = new Date(); + var mili = now.getTime(); + + Joi.date().validate(mili.toString(), function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(now); + done(); + }); + }); + + describe('#validate', function () { + + describe('min', function () { + + it('validates min', function (done) { + + Helper.validate(Joi.date().min('1-1-2000 UTC'), [ + ['1-1-2001 UTC', true], + ['1-1-2000 UTC', true], + [0, false], + ['0', false], + ['-1', false], + ['1-1-1999 UTC', false] + ], done); + }); + + it('accepts "now" as the min date', function (done) { + + var future = new Date(Date.now() + 1000000); + + Joi.date().min('now').validate(future, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(future); + done(); + }); + }); + + it('errors if .min("now") is used with a past date', function (done) { + + var past = new Date(Date.now() - 1000000); + + Joi.date().min('now').validate(past, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('accepts references as min date', function (done) { + + var schema = Joi.object({ a: Joi.date(), b: Joi.date().min(Joi.ref('a')) }); + var now = Date.now(); + + Helper.validate(schema, [ + [{ a: now, b: now }, true], + [{ a: now, b: now + 1e3 }, true], + [{ a: now, b: now - 1e3 }, false] + ], done); + }); + + it('accepts context references as min date', function (done) { + + var schema = Joi.object({ b: Joi.date().min(Joi.ref('$a')) }); + var now = Date.now(); + + Helper.validate(schema, [ + [{ b: now }, true, { context: { a: now } }], + [{ b: now + 1e3 }, true, { context: { a: now } }], + [{ b: now - 1e3 }, false, { context: { a: now } }] + ], done); + }); + + it('errors if reference is not a date', function (done) { + + var schema = Joi.object({ a: Joi.string(), b: Joi.date().min(Joi.ref('a')) }); + var now = Date.now(); + + Helper.validate(schema, [ + [{ a: 'abc', b: now }, false, null, 'child "b" fails because ["b" references "a" which is not a date]'], + [{ a: '123', b: now }, true], + [{ a: (now + 1e3).toString(), b: now }, false, null, /^child "b" fails because \["b" must be larger than or equal to/] + ], done); + }); + + it('errors if context reference is not a date', function (done) { + + var schema = Joi.object({ b: Joi.date().min(Joi.ref('$a')) }); + var now = Date.now(); + + Helper.validate(schema, [ + [{ b: now }, false, { context: { a: 'abc' } }, 'child "b" fails because ["b" references "a" which is not a date]'], + [{ b: now }, false, { context: { a: (now + 1e3).toString() } }, /^child "b" fails because \["b" must be larger than or equal to/] + ], done); + }); + }); + + describe('max', function () { + + it('validates max', function (done) { + + Helper.validate(Joi.date().max('1-1-1970 UTC'), [ + ['1-1-1971 UTC', false], + ['1-1-1970 UTC', true], + [0, true], + [1, false], + ['0', true], + ['-1', true], + ['1-1-2014 UTC', false] + ], done); + }); + + it('accepts "now" as the max date', function (done) { + + var past = new Date(Date.now() - 1000000); + + Joi.date().max('now').validate(past, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal(past); + done(); + }); + }); + + it('errors if .max("now") is used with a future date', function (done) { + + var future = new Date(Date.now() + 1000000); + + Joi.date().max('now').validate(future, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('accepts references as max date', function (done) { + + var schema = Joi.object({ a: Joi.date(), b: Joi.date().max(Joi.ref('a')) }); + var now = Date.now(); + + Helper.validate(schema, [ + [{ a: now, b: now }, true], + [{ a: now, b: now + 1e3 }, false], + [{ a: now, b: now - 1e3 }, true] + ], done); + }); + + it('accepts references as max date', function (done) { + + var schema = Joi.object({ b: Joi.date().max(Joi.ref('$a')) }); + var now = Date.now(); + + Helper.validate(schema, [ + [{ b: now }, true, { context: { a: now } }], + [{ b: now + 1e3 }, false, { context: { a: now } }], + [{ b: now - 1e3 }, true, { context: { a: now } }] + ], done); + }); + + it('errors if reference is not a date', function (done) { + + var schema = Joi.object({ a: Joi.string(), b: Joi.date().max(Joi.ref('a')) }); + var now = Date.now(); + + Helper.validate(schema, [ + [{ a: 'abc', b: new Date() }, false, null, 'child "b" fails because ["b" references "a" which is not a date]'], + [{ a: '100000000000000', b: now }, true], + [{ a: (now - 1e3).toString(), b: now }, false, null, /^child "b" fails because \["b" must be less than or equal to/] + ], done); + }); + + it('errors if context reference is not a date', function (done) { + + var schema = Joi.object({ b: Joi.date().max(Joi.ref('$a')) }); + var now = Date.now(); + + Helper.validate(schema, [ + [{ b: now }, false, { context: { a: 'abc' } }, 'child "b" fails because ["b" references "a" which is not a date]'], + [{ b: now }, true, { context: { a: '100000000000000' } }], + [{ b: now }, false, { context: { a: (now - 1e3).toString() } }, /^child "b" fails because \["b" must be less than or equal to/] + ], done); + }); + }); + + it('validates only valid dates', function (done) { + + Helper.validate(Joi.date(), [ + ['1-1-2013 UTC', true], + ['not a valid date', false], + [new Date('not a valid date'), false] + ], done); + }); + + describe('#iso', function () { + + it('validates isoDate', function (done) { + + Helper.validate(Joi.date().iso(), [ + ['2013-06-07T14:21:46.295Z', true], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', true], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', true], + ['2013-06-07T14:21:46Z', true], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', true], + ['2013-06-07T14:21:46-07:00', true], + ['2013-06-07T14:21Z', true], + ['2013-06-07T14:21+07:00', true], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', true], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', true], + ['2013-06-07T', false], + ['2013-06-07T14:21', true], + ['1-1-2013', false] + ], done); + }); + + it('validates isoDate with a friendly error message', function (done) { + + var schema = { item: Joi.date().iso() }; + Joi.compile(schema).validate({ item: 'something' }, function (err, value) { + + expect(err.message).to.contain('must be a valid ISO 8601 date'); + done(); + }); + }); + + it('validates isoDate after clone', function (done) { + + var schema = { item: Joi.date().iso().clone() }; + Joi.compile(schema).validate({ item: '2013-06-07T14:21:46.295Z' }, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + }); + + describe('#format', function () { + + it('validates custom format', function (done) { + + Helper.validate(Joi.date().format('DD#YYYY$MM'), [ + ['07#2013$06', true], + ['2013-06-07', false] + ], done); + }); + + it('validates several custom formats', function (done) { + + Helper.validate(Joi.date().format(['DD#YYYY$MM', 'YY|DD|MM']), [ + ['13|07|06', true], + ['2013-06-07', false] + ], done); + }); + + it('fails with bad formats', function (done) { + + expect(function () { + + Joi.date().format(true); + }).to.throw('Invalid format.'); + + expect(function () { + + Joi.date().format(['YYYYMMDD', true]); + }).to.throw('Invalid format.'); + done(); + }); + }); + }); +});
@@ -0,0 +1,459 @@
+// Load modules + +var Lab = require('lab'); +var Code = require('code'); +var Joi = require('../lib'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +describe('errors', function () { + + it('supports custom errors when validating types', function (done) { + + var schema = Joi.object({ + email: Joi.string().email(), + date: Joi.date(), + alphanum: Joi.string().alphanum(), + min: Joi.string().min(3), + max: Joi.string().max(3), + required: Joi.string().required(), + xor: Joi.string(), + renamed: Joi.string().valid('456'), + notEmpty: Joi.string().required() + }).rename('renamed', 'required').without('required', 'xor').without('xor', 'required'); + + var input = { + email: 'invalid-email', + date: 'invalid-date', + alphanum: '\b\n\f\r\t', + min: 'ab', + max: 'abcd', + required: 'hello', + xor: '123', + renamed: '456', + notEmpty: '' + }; + + var lang = { + any: { + empty: '3' + }, + date: { + base: '18' + }, + string: { + base: '13', + min: '14', + max: '15', + alphanum: '16', + email: '19' + }, + object: { + without: '7', + rename: { + override: '11' + } + } + }; + + Joi.validate(input, schema, { abortEarly: false, language: lang }, function (err, value) { + + expect(err).to.exist(); + expect(err.name).to.equal('ValidationError'); + expect(err.message).to.equal('"value" 11. child "email" fails because ["email" 19]. child "date" fails because ["date" 18]. child "alphanum" fails because ["alphanum" 16]. child "min" fails because ["min" 14]. child "max" fails because ["max" 15]. child "notEmpty" fails because ["notEmpty" 3]. "required" 7. "xor" 7'); + done(); + }); + }); + + it('does not prefix with key when language uses context.key', function (done) { + + Joi.valid('sad').options({ language: { any: { allowOnly: 'my hero "{{key}}" is not {{valids}}' } } }).validate(5, function (err, value) { + + expect(err.message).to.equal('my hero "value" is not [sad]'); + done(); + }); + }); + + it('escapes unsafe keys', function (done) { + + var schema = { + 'a()': Joi.number() + }; + + Joi.validate({ 'a()': 'x' }, schema, function (err, value) { + + expect(err.message).to.equal('child "a()" fails because ["a()" must be a number]'); + + Joi.validate({ 'b()': 'x' }, schema, function (err2, value2) { + + expect(err2.message).to.equal('"b()" is not allowed'); + done(); + }); + }); + }); + + it('returns error type in validation error', function (done) { + + var input = { + notNumber: '', + notString: true, + notBoolean: 9 + }; + + var schema = { + notNumber: Joi.number().required(), + notString: Joi.string().required(), + notBoolean: Joi.boolean().required() + }; + + Joi.validate(input, schema, { abortEarly: false }, function (err, value) { + + expect(err).to.exist(); + expect(err.details).to.have.length(3); + expect(err.details[0].type).to.equal('number.base'); + expect(err.details[1].type).to.equal('string.base'); + expect(err.details[2].type).to.equal('boolean.base'); + done(); + }); + }); + + it('returns a full path to an error value on an array (items)', function (done) { + + var schema = Joi.array().items(Joi.array().items({ x: Joi.number() })); + var input = [ + [{ x: 1 }], + [{ x: 1 }, { x: 'a' }] + ]; + + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.details[0].path).to.equal('1.1.x'); + done(); + }); + }); + + it('returns a full path to an error value on an array (items forbidden)', function (done) { + + var schema = Joi.array().items(Joi.array().items(Joi.object({ x: Joi.string() }).forbidden())); + var input = [ + [{ x: 1 }], + [{ x: 1 }, { x: 'a' }] + ]; + + schema.validate(input, function (err, value) { + + expect(err).to.exist(); + expect(err.details[0].path).to.equal('1.1'); + done(); + }); + }); + + it('returns a full path to an error value on an object', function (done) { + + var schema = { + x: Joi.array().items({ x: Joi.number() }) + }; + + var input = { + x: [{ x: 1 }, { x: 'a' }] + }; + + Joi.validate(input, schema, function (err, value) { + + expect(err).to.exist(); + expect(err.details[0].path).to.equal('x.1.x'); + done(); + }); + }); + + it('overrides root key language', function (done) { + + Joi.string().options({ language: { root: 'blah' } }).validate(4, function (err, value) { + + expect(err.message).to.equal('"blah" must be a string'); + done(); + }); + }); + + it('overrides label key language', function (done) { + + Joi.string().options({ language: { key: 'my own {{!key}} ' } }).validate(4, function (err, value) { + + expect(err.message).to.equal('my own value must be a string'); + done(); + }); + }); + + it('overrides wrapArrays', function (done) { + + Joi.array().items(Joi.boolean()).options({ language: { messages: { wrapArrays: false } } }).validate([4], function (err, value) { + + expect(err.message).to.equal('"value" at position 0 fails because "0" must be a boolean'); + done(); + }); + }); + + it('allows html escaping', function (done) { + + Joi.string().options({ language: { root: 'blah', label: 'bleh' } }).validate(4, function (err, value) { + + expect(err.message).to.equal('"bleh" must be a string'); + done(); + }); + }); + + it('provides context with the error', function (done) { + + Joi.object({ length: Joi.number().min(3).required() }).validate({ length: 1 }, function (err) { + + expect(err.details).to.deep.equal([{ + message: '"length" must be larger than or equal to 3', + path: 'length', + type: 'number.min', + context: { + limit: 3, + key: 'length', + value: 1 + } + }]); + done(); + }); + }); + + it('has a name that is ValidationError', function (done) { + + var schema = Joi.number(); + schema.validate('a', function (validateErr) { + + expect(validateErr).to.exist(); + expect(validateErr.name).to.be.equal('ValidationError'); + + try { + Joi.assert('a', schema); + throw new Error('should not reach that'); + } + catch (assertErr) { + expect(assertErr.name).to.be.equal('ValidationError'); + } + + try { + Joi.assert('a', schema, 'foo'); + throw new Error('should not reach that'); + } + catch (assertErr) { + expect(assertErr.name).to.be.equal('ValidationError'); + } + + try { + Joi.assert('a', schema, new Error('foo')); + throw new Error('should not reach that'); + } + catch (assertErr) { + expect(assertErr.name).to.equal('Error'); + done(); + } + }); + }); + + describe('#annotate', function () { + + it('annotates error', function (done) { + + var object = { + a: 'm', + y: { + b: { + c: 10 + } + } + }; + + var schema = { + a: Joi.string().valid('a', 'b', 'c', 'd'), + y: Joi.object({ + u: Joi.string().valid(['e', 'f', 'g', 'h']).required(), + b: Joi.string().valid('i', 'j').allow(false), + d: Joi.object({ + x: Joi.string().valid('k', 'l').required(), + c: Joi.number() + }) + }) + }; + + Joi.validate(object, schema, { abortEarly: false }, function (err, value) { + + expect(err).to.exist(); + expect(err.annotate()).to.equal('{\n \"y\": {\n \"b\" \u001b[31m[1]\u001b[0m: {\n \"c\": 10\n },\n \u001b[41m\"u\"\u001b[0m\u001b[31m [2]: -- missing --\u001b[0m\n },\n "a" \u001b[31m[3]\u001b[0m: \"m\"\n}\n\u001b[31m\n[1] "a" must be one of [a, b, c, d]\n[2] "u" is required\n[3] "b" must be a string\u001b[0m'); + done(); + }); + }); + + it('annotates error within array', function (done) { + + var object = { + a: [1, 2, 3, 4, 2, 5] + }; + + var schema = { + a: Joi.array().items(Joi.valid(1, 2)) + }; + + Joi.validate(object, schema, { abortEarly: false }, function (err, value) { + + expect(err).to.exist(); + expect(err.annotate()).to.equal('{\n \"a\": [\n 1,\n 2,\n 3, \u001b[31m[1]\u001b[0m\n 4, \u001b[31m[2]\u001b[0m\n 2,\n 5 \u001b[31m[3]\u001b[0m\n ]\n}\n\u001b[31m\n[1] \"2\" must be one of [1, 2]\n[2] \"3\" must be one of [1, 2]\n[3] \"5\" must be one of [1, 2]\u001b[0m'); + done(); + }); + }); + + it('annotates error within array multiple times on the same element', function (done) { + + var object = { + a: [2, 3, 4] + }; + + var schema = { + a: Joi.array().items(Joi.number().min(4).max(2)) + }; + + Joi.validate(object, schema, { abortEarly: false }, function (err, value) { + + expect(err).to.exist(); + expect(err.annotate()).to.equal('{\n \"a\": [\n 2, \u001b[31m[1]\u001b[0m\n 3, \u001b[31m[3, 2]\u001b[0m\n 4 \u001b[31m[4]\u001b[0m\n ]\n}\n\u001b[31m\n[1] \"0\" must be larger than or equal to 4\n[2] \"1\" must be larger than or equal to 4\n[3] \"1\" must be less than or equal to 2\n[4] \"2\" must be less than or equal to 2\u001b[0m'); + done(); + }); + }); + + it('annotates error within array when it is an object', function (done) { + + var object = { + a: [{ b: 2 }] + }; + + var schema = { + a: Joi.array().items(Joi.number()) + }; + + Joi.validate(object, schema, { abortEarly: false }, function (err, value) { + + expect(err).to.exist(); + expect(err.annotate()).to.equal('{\n \"a\": [\n { \u001b[31m[1]\u001b[0m\n \"b\": 2\n }\n ]\n}\n\u001b[31m\n[1] \"0\" must be a number\u001b[0m'); + done(); + }); + }); + + it('annotates error within multiple arrays and multiple times on the same element', function (done) { + + var object = { + a: [2, 3, 4], + b: [2, 3, 4] + }; + + var schema = { + a: Joi.array().items(Joi.number().min(4).max(2)), + b: Joi.array().items(Joi.number().min(4).max(2)) + }; + + Joi.validate(object, schema, { abortEarly: false }, function (err, value) { + + expect(err).to.exist(); + expect(err.annotate()).to.equal('{\n \"a\": [\n 2, \u001b[31m[1]\u001b[0m\n 3, \u001b[31m[3, 2]\u001b[0m\n 4 \u001b[31m[4]\u001b[0m\n ],\n \"b\": [\n 2, \u001b[31m[5]\u001b[0m\n 3, \u001b[31m[7, 6]\u001b[0m\n 4 \u001b[31m[8]\u001b[0m\n ]\n}\n\u001b[31m\n[1] \"0\" must be larger than or equal to 4\n[2] \"1\" must be larger than or equal to 4\n[3] \"1\" must be less than or equal to 2\n[4] \"2\" must be less than or equal to 2\n[5] \"0\" must be larger than or equal to 4\n[6] \"1\" must be larger than or equal to 4\n[7] \"1\" must be less than or equal to 2\n[8] \"2\" must be less than or equal to 2\u001b[0m'); + done(); + }); + }); + + it('displays alternatives fail as a single line', function (done) { + + var schema = { + x: [ + Joi.string(), + Joi.number(), + Joi.date() + ] + }; + + Joi.validate({ x: true }, schema, function (err, value) { + + expect(err).to.exist(); + expect(err.annotate()).to.equal('{\n \"x\" \u001b[31m[1, 2, 3]\u001b[0m: true\n}\n\u001b[31m\n[1] "x" must be a string\n[2] "x" must be a number\n[3] "x" must be a number of milliseconds or valid date string\u001b[0m'); + done(); + }); + }); + + it('annotates circular input', function (done) { + + var schema = { + x: Joi.object({ + y: Joi.object({ + z: Joi.number() + }) + }) + }; + + var input = {}; + input.x = input; + + Joi.validate(input, schema, function (err, value) { + + expect(err).to.exist(); + expect(err.annotate()).to.equal('{\n \"x\" \u001b[31m[1]\u001b[0m: \"[Circular ~]\"\n}\n\u001b[31m\n[1] \"x\" is not allowed\u001b[0m'); + done(); + }); + }); + + it('annotates deep circular input', function (done) { + + var schema = { + x: Joi.object({ + y: Joi.object({ + z: Joi.number() + }) + }) + }; + + var input = { x: { y: {} } }; + input.x.y.z = input.x.y; + + Joi.validate(input, schema, function (err, value) { + + expect(err).to.exist(); + expect(err.annotate()).to.equal('{\n \"x\": {\n \"y\": {\n \"z\" \u001b[31m[1]\u001b[0m: \"[Circular ~.x.y]\"\n }\n }\n}\n\u001b[31m\n[1] \"z\" must be a number\u001b[0m'); + done(); + }); + }); + + it('annotates deep circular input with extra keys', function (done) { + + var schema = { + x: Joi.object({ + y: Joi.object({ + z: Joi.number() + }) + }) + }; + + var input = { x: { y: { z: 1, foo: {} } } }; + input.x.y.foo = input.x.y; + + Joi.validate(input, schema, function (err, value) { + + expect(err).to.exist(); + expect(err.annotate()).to.equal('{\n \"x\": {\n \"y\": {\n \"z\": 1,\n \"foo\" \u001b[31m[1]\u001b[0m: \"[Circular ~.x.y]\"\n }\n }\n}\n\u001b[31m\n[1] \"foo\" is not allowed\u001b[0m'); + done(); + }); + }); + }); +});
@@ -0,0 +1,113 @@
+// Load modules + +var Code = require('code'); +var Lab = require('lab'); +var Joi = require('../lib'); +var Helper = require('./helper'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +describe('func', function () { + + it('validates a function', function (done) { + + Helper.validate(Joi.func().required(), [ + [function () { }, true], + ['', false] + ], done); + }); + + it('validates a function with keys', function (done) { + + var a = function () { }; + a.a = 'abc'; + + var b = function () { }; + b.a = 123; + + Helper.validate(Joi.func().keys({ a: Joi.string().required() }).required(), [ + [function () { }, false], + [a, true], + [b, false], + ['', false] + ], done); + }); + + it('keeps validated value as a function', function (done) { + + var schema = Joi.func().keys({ a: Joi.number() }); + + var b = 'abc'; + var value = function () { + + return b; + }; + + value.a = '123'; + + schema.validate(value, function (err, validated) { + + expect(validated).to.be.a.function(); + expect(validated()).to.equal('abc'); + expect(validated).to.not.equal(value); + done(); + }); + }); + + it('retains validated value prototype', function (done) { + + var schema = Joi.func().keys({ a: Joi.number() }); + + var value = function () { + + this.x = 'o'; + }; + + value.prototype.get = function () { + + return this.x; + }; + + schema.validate(value, function (err, validated) { + + expect(validated).to.be.a.function(); + var p = new validated(); + expect(p.get()).to.equal('o'); + expect(validated).to.not.equal(value); + done(); + }); + }); + + it('keeps validated value as a function (no clone)', function (done) { + + var schema = Joi.func(); + + var b = 'abc'; + var value = function () { + + return b; + }; + + value.a = '123'; + + schema.validate(value, function (err, validated) { + + expect(validated).to.be.a.function(); + expect(validated()).to.equal('abc'); + expect(validated).to.equal(value); + done(); + }); + }); +});
@@ -0,0 +1,63 @@
+// Load modules + +var Code = require('code'); +var Joi = require('../'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var expect = Code.expect; + + +exports.validate = function (schema, config, callback) { + + return exports.validateOptions(schema, config, null, callback); +}; + + +exports.validateOptions = function (schema, config, options, callback) { + + var compiled = Joi.compile(schema); + for (var i = 0, il = config.length; i < il; ++i) { + + var item = config[i]; + var result = Joi.validate(item[0], compiled, item[2] || options); + + var err = result.error; + var value = result.value; + + if (err !== null && item[1]) { + console.log(err); + } + + if (err === null && !item[1]) { + console.log(item[0]); + } + + expect(err === null).to.equal(item[1]); + + if (item.length >= 4) { + var comparator = item[3]; + if (item[1]) { + expect(value).to.deep.equal(comparator); + } + else { + if (comparator instanceof RegExp) { + expect(err.message).to.match(comparator); + } + else { + expect(err.message).to.deep.equal(comparator); + } + } + } + } + + if (callback) { + callback(); + } +};
@@ -0,0 +1,1692 @@
+// Load modules + +var Lab = require('lab'); +var Code = require('code'); +var Joi = require('../lib'); +var Helper = require('./helper'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +describe('Joi', function () { + + it('validates object', function (done) { + + var schema = Joi.object({ + a: Joi.number().min(0).max(3), + b: Joi.string().valid('a', 'b', 'c'), + c: Joi.string().email().optional() + }).without('a', 'none'); + + var obj = { + a: 1, + b: 'a', + c: 'joe@example.com' + }; + + schema.validate(obj, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('keeps schema immutable', function (done) { + + var a = Joi.string(); + var b = a.valid('b'); + + Helper.validate(a, [ + ['a', true], + ['b', true], + [5, false] + ], function () { + + Helper.validate(b, [ + ['a', false], + ['b', true], + [5, false] + ], done); + }); + + }); + + it('validates null', function (done) { + + Joi.string().validate(null, function (err, value) { + + expect(err).to.exist(); + expect(err.annotate()).to.equal('{\n \u001b[41m\"value\"\u001b[0m\u001b[31m [1]: -- missing --\u001b[0m\n}\n\u001b[31m\n[1] "value" must be a string\u001b[0m'); + done(); + }); + }); + + it('validates null schema', function (done) { + + Helper.validate(null, [ + ['a', false], + [null, true] + ], done); + }); + + it('validates number literal', function (done) { + + Helper.validate(5, [ + [6, false], + [5, true] + ], done); + }); + + it('validates string literal', function (done) { + + Helper.validate('5', [ + ['6', false], + ['5', true] + ], done); + }); + + it('validates boolean literal', function (done) { + + Helper.validate(true, [ + [false, false], + [true, true] + ], done); + }); + + it('validates date literal', function (done) { + + var now = Date.now(); + Helper.validate(new Date(now), [ + [new Date(now), true], + [now, true], + [now * 2, false] + ], done); + }); + + it('validates complex literal', function (done) { + + var schema = ['key', 5, { a: true, b: [/^a/, 'boom'] }]; + Helper.validate(schema, [ + ['key', true], + [5, true], + ['other', false], + [6, false], + [{ c: 5 }, false], + [{}, true], + [{ b: 'abc' }, true], + [{ a: true, b: 'boom' }, true], + [{ a: 5, b: 'a' }, false] + ], done); + }); + + it('validates a compiled complex literal', function (done) { + + var schema = Joi.compile(['key', 5, { a: true, b: [/^a/, 'boom'] }]); + Helper.validate(schema, [ + ['key', true], + [5, true], + ['other', false], + [6, false], + [{ c: 5 }, false], + [{}, true], + [{ b: 'abc' }, true], + [{ a: true, b: 'boom' }, true], + [{ a: 5, b: 'a' }, false] + ], done); + }); + + it('validates regex directly', function (done) { + + Joi.compile(/^5$/).validate('5', function (err, value) { + + expect(err).to.not.exist(); + Joi.compile(/.{2}/).validate('6', function (err2, value2) { + + expect(err2).to.exist(); + done(); + }); + }); + }); + + it('validated with', function (done) { + + var schema = Joi.object({ + txt: Joi.string(), + upc: Joi.string() + }).with('txt', 'upc'); + + Joi.validate({ txt: 'a' }, schema, { abortEarly: false }, function (err, value) { + + expect(err.message).to.equal('"txt" missing required peer "upc"'); + + Helper.validate(schema, [ + [{ upc: 'test' }, true], + [{ txt: 'test' }, false], + [{ txt: 'test', upc: null }, false], + [{ txt: 'test', upc: '' }, false], + [{ txt: 'test', upc: undefined }, false], + [{ txt: 'test', upc: 'test' }, true] + ], done); + }); + }); + + it('validated without', function (done) { + + var schema = Joi.object({ + txt: Joi.string(), + upc: Joi.string() + }).without('txt', 'upc'); + + Joi.validate({ txt: 'a', upc: 'b' }, schema, { abortEarly: false }, function (err, value) { + + expect(err.message).to.equal('"txt" conflict with forbidden peer "upc"'); + + Helper.validate(schema, [ + [{ upc: 'test' }, true], + [{ txt: 'test' }, true], + [{ txt: 'test', upc: null }, false], + [{ txt: 'test', upc: '' }, false], + [{ txt: 'test', upc: undefined }, true], + [{ txt: 'test', upc: 'test' }, false] + ], done); + }); + }); + + it('validates xor', function (done) { + + var schema = Joi.object({ + txt: Joi.string(), + upc: Joi.string() + }).xor('txt', 'upc'); + + Joi.validate({}, schema, { abortEarly: false }, function (err, value) { + + expect(err.message).to.equal('"value" must contain at least one of [txt, upc]'); + + Helper.validate(schema, [ + [{ upc: null }, false], + [{ upc: 'test' }, true], + [{ txt: null }, false], + [{ txt: 'test' }, true], + [{ txt: 'test', upc: null }, false], + [{ txt: 'test', upc: '' }, false], + [{ txt: '', upc: 'test' }, false], + [{ txt: null, upc: 'test' }, false], + [{ txt: undefined, upc: 'test' }, true], + [{ txt: 'test', upc: undefined }, true], + [{ txt: 'test', upc: '' }, false], + [{ txt: 'test', upc: null }, false], + [{ txt: '', upc: undefined }, false], + [{ txt: '', upc: '' }, false], + [{ txt: 'test', upc: 'test' }, false] + ], done); + }); + }); + + it('validates multiple peers xor', function (done) { + + var schema = Joi.object({ + txt: Joi.string(), + upc: Joi.string(), + code: Joi.string() + }).xor('txt', 'upc', 'code'); + + Helper.validate(schema, [ + [{ upc: 'test' }, true], + [{ txt: 'test' }, true], + [{}, false] + ], done); + }); + + it('validates xor with number types', function (done) { + + var schema = Joi.object({ + code: Joi.number(), + upc: Joi.number() + }).xor('code', 'upc'); + + Helper.validate(schema, [ + [{ upc: 123 }, true], + [{ code: 456 }, true], + [{ code: 456, upc: 123 }, false], + [{}, false] + ], done); + }); + + it('validates xor when empty value of peer allowed', function (done) { + + var schema = Joi.object({ + code: Joi.string(), + upc: Joi.string().allow('') + }).xor('code', 'upc'); + + Helper.validate(schema, [ + [{ upc: '' }, true], + [{ upc: '123' }, true], + [{ code: '456' }, true], + [{ code: '456', upc: '' }, false], + [{}, false] + ], done); + }); + + it('validates or', function (done) { + + var schema = Joi.object({ + txt: Joi.string(), + upc: Joi.string().allow(null, ''), + code: Joi.number() + }).or('txt', 'upc', 'code'); + + Joi.validate({}, schema, { abortEarly: false }, function (err, value) { + + expect(err.message).to.equal('"value" must contain at least one of [txt, upc, code]'); + + Helper.validate(schema, [ + [{ upc: null }, true], + [{ upc: 'test' }, true], + [{ txt: null }, false], + [{ txt: 'test' }, true], + [{ code: null }, false], + [{ code: 123 }, true], + [{ txt: 'test', upc: null }, true], + [{ txt: 'test', upc: '' }, true], + [{ txt: '', upc: 'test' }, false], + [{ txt: null, upc: 'test' }, false], + [{ txt: undefined, upc: 'test' }, true], + [{ txt: 'test', upc: undefined }, true], + [{ txt: 'test', upc: '' }, true], + [{ txt: 'test', upc: null }, true], + [{ txt: '', upc: undefined }, false], + [{ txt: '', upc: undefined, code: 999 }, false], + [{ txt: '', upc: undefined, code: undefined }, false], + [{ txt: '', upc: '' }, false], + [{ txt: 'test', upc: 'test' }, true], + [{ txt: 'test', upc: 'test', code: 322 }, true] + ], done); + }); + }); + + it('validates and', function (done) { + + var schema = Joi.object({ + txt: Joi.string(), + upc: Joi.string().allow(null, ''), + code: Joi.number() + }).and('txt', 'upc', 'code'); + + Joi.validate({ txt: 'x' }, schema, { abortEarly: false }, function (err, value) { + + expect(err.message).to.equal('"value" contains [txt] without its required peers [upc, code]'); + + Helper.validate(schema, [ + [{}, true], + [{ upc: null }, false], + [{ upc: 'test' }, false], + [{ txt: null }, false], + [{ txt: 'test' }, false], + [{ code: null }, false], + [{ code: 123 }, false], + [{ txt: 'test', upc: null }, false], + [{ txt: 'test', upc: '' }, false], + [{ txt: '', upc: 'test' }, false], + [{ txt: null, upc: 'test' }, false], + [{ txt: undefined, upc: 'test' }, false], + [{ txt: 'test', upc: undefined }, false], + [{ txt: 'test', upc: '' }, false], + [{ txt: 'test', upc: null }, false], + [{ txt: '', upc: undefined }, false], + [{ txt: '', upc: undefined, code: 999 }, false], + [{ txt: '', upc: undefined, code: undefined }, false], + [{ txt: '', upc: '' }, false], + [{ txt: 'test', upc: 'test' }, false], + [{ txt: 'test', upc: 'test', code: 322 }, true], + [{ txt: 'test', upc: null, code: 322 }, true] + ], done); + }); + }); + + it('validates nand()', function (done) { + + var schema = Joi.object({ + txt: Joi.string(), + upc: Joi.string().allow(null, ''), + code: Joi.number() + }).nand('txt', 'upc', 'code'); + + Joi.validate({ txt: 'x', upc: 'y', code: 123 }, schema, { abortEarly: false }, function (err, value) { + + expect(err.message).to.equal('"txt" must not exist simultaneously with [upc, code]'); + + Helper.validate(schema, [ + [{}, true], + [{ upc: null }, true], + [{ upc: 'test' }, true], + [{ txt: 'test' }, true], + [{ code: 123 }, true], + [{ txt: 'test', upc: null }, true], + [{ txt: 'test', upc: '' }, true], + [{ txt: undefined, upc: 'test' }, true], + [{ txt: 'test', upc: undefined }, true], + [{ txt: 'test', upc: '' }, true], + [{ txt: 'test', upc: null }, true], + [{ txt: 'test', upc: undefined, code: 999 }, true], + [{ txt: 'test', upc: 'test' }, true], + [{ txt: 'test', upc: 'test', code: 322 }, false], + [{ txt: 'test', upc: null, code: 322 }, false] + ], done); + }); + }); + + it('validates an array of valid types', function (done) { + + var schema = Joi.object({ + auth: [ + Joi.object({ + mode: Joi.string().valid('required', 'optional', 'try').allow(null) + }).allow(null), + Joi.string(), + Joi.boolean() + ] + }); + + schema.validate({ auth: { mode: 'none' } }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('child "auth" fails because [child "mode" fails because ["mode" must be one of [required, optional, try, null]], "auth" must be a string, "auth" must be a boolean]'); + + Helper.validate(schema, [ + [{ auth: { mode: 'try' } }, true], + [{ something: undefined }, false], + [{ auth: { something: undefined } }, false], + [{ auth: null }, true], + [{ auth: undefined }, true], + [{}, true], + [{ auth: true }, true], + [{ auth: 123 }, false] + ], done); + }); + }); + + it('validates alternatives', function (done) { + + var schema = Joi.object({ + auth: Joi.alternatives( + Joi.object({ + mode: Joi.string().valid('required', 'optional', 'try').allow(null) + }).allow(null), + Joi.string(), + Joi.boolean() + ) + }); + + schema.validate({ auth: { mode: 'none' } }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('child "auth" fails because [child "mode" fails because ["mode" must be one of [required, optional, try, null]], "auth" must be a string, "auth" must be a boolean]'); + + Helper.validate(schema, [ + [{ auth: { mode: 'try' } }, true], + [{ something: undefined }, false], + [{ auth: { something: undefined } }, false], + [{ auth: null }, true], + [{ auth: undefined }, true], + [{}, true], + [{ auth: true }, true], + [{ auth: 123 }, false] + ], done); + }); + }); + + it('validates required alternatives', function (done) { + + var schema = { + a: Joi.alternatives( + Joi.string().required(), + Joi.boolean().required() + ) + }; + + Helper.validate(schema, [ + [{ a: null }, false], + [{ a: undefined }, true], + [{}, true], + [{ a: true }, true], + [{ a: 'true' }, true], + [{ a: 123 }, false], + [{ a: { c: 1 } }, false], + [{ b: undefined }, false] + ], done); + }); + + it('validates required [] alternatives', function (done) { + + var schema = { + a: [ + Joi.string().required(), + Joi.boolean().required() + ] + }; + + Helper.validate(schema, [ + [{ a: null }, false], + [{ a: undefined }, true], + [{}, true], + [{ a: true }, true], + [{ a: 'true' }, true], + [{ a: 123 }, false], + [{ a: { c: 1 } }, false], + [{ b: undefined }, false] + ], done); + }); + + it('validates an array of string with valid', function (done) { + + var schema = { + brand: Joi.array().items(Joi.string().valid('amex', 'visa')) + }; + + Helper.validate(schema, [ + [{ brand: ['amex'] }, true], + [{ brand: ['visa', 'mc'] }, false] + ], done); + }); + + it('validates pre and post convert value', function (done) { + + var schema = Joi.number().valid(5); + + Helper.validate(schema, [ + [5, true], + ['5', true] + ], done); + }); + + it('does not change object when validation fails', function (done) { + + var schema = Joi.object({ + a: Joi.number().valid(2) + }); + + var obj = { + a: '5' + }; + + schema.validate(obj, function (err, value) { + + expect(err).to.exist(); + expect(value.a).to.equal('5'); + done(); + }); + }); + + it('does not set optional keys when missing', function (done) { + + var schema = Joi.object({ + a: Joi.number() + }); + + var obj = {}; + + schema.validate(obj, function (err, value) { + + expect(err).to.not.exist(); + expect(value.hasOwnProperty('a')).to.equal(false); + done(); + }); + }); + + it('invalidates pre and post convert value', function (done) { + + var schema = Joi.number().invalid(5); + + Helper.validate(schema, [ + [5, false], + ['5', false] + ], done); + }); + + it('invalidates missing peers', function (done) { + + var schema = Joi.object({ + username: Joi.string(), + password: Joi.string() + }).with('username', 'password').without('password', 'access_token'); + + schema.validate({ username: 'bob' }, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('validates config where the root item is a joi type', function (done) { + + Joi.boolean().allow(null).validate(true, function (err, value) { + + expect(err).to.be.null(); + Joi.object().validate({ auth: { mode: 'try' } }, function (err2, value2) { + + expect(err2).to.be.null(); + + Joi.object().validate(true, function (err3, value3) { + + expect(err3.message).to.contain('"value" must be an object'); + + Joi.string().validate(true, function (err4, value4) { + + expect(err4.message).to.contain('"value" must be a string'); + + Joi.string().email().validate('test@test.com', function (err5, value5) { + + expect(err5).to.be.null(); + Joi.object({ param: Joi.string().required() }).validate({ param: 'item' }, function (err6, value6) { + + expect(err6).to.be.null(); + done(); + }); + }); + }); + }); + }); + }); + }); + + it('converts string to number', function (done) { + + var schema = Joi.object({ + a: Joi.number() + }); + + var input = { a: '5' }; + schema.validate(input, function (err, value) { + + expect(err).to.be.null(); + expect(value.a).to.equal(5); + expect(input.a).to.equal('5'); + done(); + }); + }); + + it('allows unknown keys in objects if no schema was given', function (done) { + + Joi.object().validate({ foo: 'bar' }, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('fails on unknown keys in objects if a schema was given', function (done) { + + Joi.object({}).validate({ foo: 'bar' }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"foo" is not allowed'); + + Joi.compile({}).validate({ foo: 'bar' }, function (err2, value2) { + + expect(err2).to.exist(); + expect(err2.message).to.equal('"foo" is not allowed'); + + Joi.compile({ other: Joi.number() }).validate({ foo: 'bar' }, function (err3, value3) { + + expect(err3).to.exist(); + expect(err3.message).to.equal('"foo" is not allowed'); + + done(); + }); + }); + }); + }); + + it('validates an unknown option', function (done) { + + var config = { + auth: Joi.object({ + mode: Joi.string().valid('required', 'optional', 'try').allow(null) + }).allow(null) + }; + + Joi.compile(config).validate({ auth: { unknown: true } }, function (err, value) { + + expect(err).to.not.be.null(); + expect(err.message).to.contain('"unknown" is not allowed'); + + Joi.compile(config).validate({ something: false }, function (err2, value2) { + + expect(err2).to.not.be.null(); + expect(err2.message).to.contain('"something" is not allowed'); + + done(); + }); + }); + }); + + it('validates required key with multiple options', function (done) { + + var config = { + module: Joi.alternatives([ + Joi.object({ + compile: Joi.func().required(), + execute: Joi.func() + }), + Joi.string() + ]).required() + }; + + Joi.compile(config).validate({}, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.contain('"module" is required'); + + Joi.compile(config).validate({ module: 'test' }, function (err2, value2) { + + expect(err2).to.be.null(); + + Joi.compile(config).validate({ module: {} }, function (err3, value3) { + + expect(err3).to.not.be.null(); + expect(err3.message).to.contain('"compile" is required'); + expect(err3.message).to.contain('"module" must be a string'); + + Joi.compile(config).validate({ module: { compile: function () { } } }, function (err4, value4) { + + expect(err4).to.be.null(); + done(); + }); + }); + }); + }); + }); + + it('validates key with required alternatives', function (done) { + + var config = { + module: Joi.alt().try( + Joi.object({ + compile: Joi.func().required(), + execute: Joi.func() + }).required(), + Joi.string().required() + ) + }; + + Joi.compile(config).validate({}, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('validates required key with alternatives', function (done) { + + var config = { + module: Joi.alt().try( + Joi.object({ + compile: Joi.func().required(), + execute: Joi.func() + }), + Joi.string() + ).required() + }; + + Joi.compile(config).validate({}, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.contain('"module" is required'); + done(); + }); + }); + + it('does not require optional numbers', function (done) { + + var config = { + position: Joi.number(), + suggestion: Joi.string() + }; + + Joi.compile(config).validate({ suggestion: 'something' }, function (err, value) { + + expect(err).to.be.null(); + + Joi.compile(config).validate({ position: 1 }, function (err2, value2) { + + expect(err2).to.be.null(); + done(); + }); + }); + }); + + it('does not require optional objects', function (done) { + + var config = { + position: Joi.number(), + suggestion: Joi.object() + }; + + Joi.compile(config).validate({ suggestion: {} }, function (err, value) { + + expect(err).to.be.null(); + + Joi.compile(config).validate({ position: 1 }, function (err2, value2) { + + expect(err2).to.be.null(); + done(); + }); + }); + }); + + it('validates object successfully when config has an array of types', function (done) { + + var schema = { + f: [Joi.number(), Joi.boolean()], + g: [Joi.string(), Joi.object()] + }; + + var obj = { + f: true, + g: 'test' + }; + + Joi.compile(schema).validate(obj, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('validates object successfully when config allows for optional key and key is missing', function (done) { + + var schema = { + h: Joi.number(), + i: Joi.string(), + j: Joi.object() + }; + + var obj = { + h: 12, + i: 'test' + }; + + Joi.compile(schema).validate(obj, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('fails validation', function (done) { + + var schema = { + a: Joi.number().min(0).max(3), + b: Joi.string().valid('a', 'b', 'c'), + c: Joi.string().email().optional() + }; + + var obj = { + a: 10, + b: 'a', + c: 'joe@example.com' + }; + + Joi.compile(schema).validate(obj, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('fails validation when the wrong types are supplied', function (done) { + + var schema = { + a: Joi.number().min(0).max(3), + b: Joi.string().valid('a', 'b', 'c'), + c: Joi.string().email().optional() + }; + + var obj = { + a: 'a', + b: 'a', + c: 'joe@example.com' + }; + + Joi.compile(schema).validate(obj, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('fails validation when missing a required parameter', function (done) { + + var obj = { + c: 10 + }; + + Joi.compile({ a: Joi.string().required() }).validate(obj, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('fails validation when missing a required parameter within an object config', function (done) { + + var obj = { + a: {} + }; + + Joi.compile({ a: Joi.object({ b: Joi.string().required() }) }).validate(obj, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('fails validation when parameter is required to be an object but is given as string', function (done) { + + var obj = { + a: 'a string' + }; + + Joi.compile({ a: Joi.object({ b: Joi.string().required() }) }).validate(obj, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('validates when parameter is required to be an object and is given correctly as a json string', function (done) { + + var schema = { + a: Joi.object({ + b: Joi.string().required() + }) + }; + + var input = { + a: '{"b":"string"}' + }; + + Joi.validate(input, schema, function (err, value) { + + expect(err).to.not.exist(); + expect(input.a).to.equal('{"b":"string"}'); + expect(value.a.b).to.equal('string'); + done(); + }); + }); + + it('fails validation when parameter is required to be an object but is given as a json string that is incorrect (number instead of string)', function (done) { + + var obj = { + a: '{"b":2}' + }; + + Joi.object({ a: Joi.object({ b: Joi.string().required() }) }).validate(obj, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('fails validation when parameter is required to be an Array but is given as string', function (done) { + + var obj = { + a: 'an array' + }; + + Joi.object({ a: Joi.array() }).validate(obj, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('validates when parameter is required to be an Array and is given correctly as a json string', function (done) { + + var obj = { + a: '[1,2]' + }; + + Joi.object({ a: Joi.array() }).validate(obj, function (err, value) { + + expect(err).to.be.null(); + done(); + }); + }); + + it('fails validation when parameter is required to be an Array but is given as a json that is incorrect (object instead of array)', function (done) { + + var obj = { + a: '{"b":2}' + }; + + Joi.object({ a: Joi.object({ b: Joi.string().required() }) }).validate(obj, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('fails validation when config is an array and fails', function (done) { + + var schema = { + d: [Joi.string(), Joi.boolean()], + e: [Joi.number(), Joi.object()] + }; + + var obj = { + d: 10, + e: 'a' + }; + + Joi.compile(schema).validate(obj, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('fails validation when config is an array and fails with extra keys', function (done) { + + var schema = { + d: [Joi.string(), Joi.boolean()], + e: [Joi.number(), Joi.object()] + }; + + var obj = { + a: 10, + b: 'a' + }; + + Joi.compile(schema).validate(obj, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('fails validation with extra keys', function (done) { + + var schema = { + a: Joi.number() + }; + + var obj = { + a: 1, + b: 'a' + }; + + Joi.compile(schema).validate(obj, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('validates missing optional key with string condition', function (done) { + + var schema = { + key: Joi.string().alphanum(false).min(8) + }; + + Joi.compile(schema).validate({}, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('validates with extra keys and remove them when stripUnknown is set', function (done) { + + var schema = { + a: Joi.number().min(0).max(3), + b: Joi.string().valid('a', 'b', 'c'), + c: Joi.string().email().optional() + }; + + var obj = { + a: 1, + b: 'a', + d: 'c' + }; + + Joi.validate(obj, schema, { stripUnknown: true, allowUnknown: true }, function (err, value) { + + expect(err).to.be.null(); + expect(value).to.deep.equal({ a: 1, b: 'a' }); + done(); + }); + }); + + it('validates dependencies when stripUnknown is set', function (done) { + + var schema = Joi.object({ + a: Joi.number(), + b: Joi.string() + }).and('a', 'b'); + + var obj = { + a: 1, + foo: 'bar' + }; + + Joi.validate(obj, schema, { stripUnknown: true }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" contains [a] without its required peers [b]'); + done(); + }); + }); + + it('fails to validate with incorrect property when asked to strip unkown keys without aborting early', function (done) { + + var schema = { + a: Joi.number().min(0).max(3), + b: Joi.string().valid('a', 'b', 'c'), + c: Joi.string().email().optional() + }; + + var obj = { + a: 1, + b: 'f', + d: 'c' + }; + + Joi.validate(obj, schema, { stripUnknown: true, abortEarly: false }, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('should pass validation with extra keys when allowUnknown is set', function (done) { + + var schema = { + a: Joi.number().min(0).max(3), + b: Joi.string().valid('a', 'b', 'c'), + c: Joi.string().email().optional() + }; + + var obj = { + a: 1, + b: 'a', + d: 'c' + }; + + Joi.validate(obj, schema, { allowUnknown: true }, function (err, value) { + + expect(err).to.be.null(); + expect(value).to.deep.equal({ a: 1, b: 'a', d: 'c' }); + done(); + }); + }); + + it('should pass validation with extra keys set', function (done) { + + var localConfig = Joi.object({ + a: Joi.number().min(0).max(3), + b: Joi.string().valid('a', 'b', 'c') + }).options({ allowUnknown: true }); + + var obj = { + a: 1, + b: 'a', + d: 'c' + }; + + localConfig.validate(obj, function (err, value) { + + expect(err).to.be.null(); + expect(value).to.deep.equal({ a: 1, b: 'a', d: 'c' }); + + localConfig.validate(value, function (err2, value2) { + + expect(err2).to.be.null(); + expect(value2).to.deep.equal({ a: 1, b: 'a', d: 'c' }); + done(); + }); + }); + }); + + + it('should pass validation with extra keys and remove them when skipExtraKeys is set locally', function (done) { + + var localConfig = Joi.object({ + a: Joi.number().min(0).max(3), + b: Joi.string().valid('a', 'b', 'c') + }).options({ stripUnknown: true, allowUnknown: true }); + + var obj = { + a: 1, + b: 'a', + d: 'c' + }; + + localConfig.validate(obj, function (err, value) { + + expect(err).to.be.null(); + expect(value).to.deep.equal({ a: 1, b: 'a' }); + + localConfig.validate(value, function (err2, value2) { + + expect(err2).to.be.null(); + expect(value2).to.deep.equal({ a: 1, b: 'a' }); + done(); + }); + }); + }); + + it('should work when the skipFunctions setting is enabled', function (done) { + + var schema = Joi.object({ username: Joi.string() }).options({ skipFunctions: true }); + var input = { username: 'test', func: function () { } }; + Joi.validate(input, schema, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('should work when the skipFunctions setting is disabled', function (done) { + + var schema = { username: Joi.string() }; + var input = { username: 'test', func: function () { } }; + + Joi.validate(input, schema, { skipFunctions: false }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.contain('"func" is not allowed'); + done(); + }); + }); + + it('should not convert values when convert is false', function (done) { + + var schema = { + arr: Joi.array().items(Joi.string()) + }; + + var input = { arr: 'foo' }; + Joi.validate(input, schema, { convert: false }, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('full errors when abortEarly is false', function (done) { + + var schema = { + a: Joi.string(), + b: Joi.string() + }; + + var input = { a: 1, b: 2 }; + + Joi.validate(input, schema, function (errOne, valueOne) { + + Joi.validate(input, schema, { abortEarly: false }, function (errFull, valueFull) { + + expect(errOne).to.exist(); + expect(errFull).to.exist(); + expect(errFull.details.length).to.be.greaterThan(errOne.details.length); + done(); + }); + }); + }); + + it('errors multiple times when abortEarly is false in a complex object', function (done) { + + var schema = Joi.object({ + test: Joi.array().items(Joi.object().keys({ + foo: Joi.string().required().max(3), + bar: Joi.string().max(5) + })), + test2: Joi.object({ + test3: Joi.array().items(Joi.object().keys({ + foo: Joi.string().required().max(3), + bar: Joi.string().max(5), + baz: Joi.object({ + test4: Joi.array().items(Joi.object().keys({ + foo: Joi.string().required().max(3), + bar: Joi.string().max(5) + })) + }) + })) + }) + }); + + var input = { + test: [{ + foo: 'test1', + bar: 'testfailed' + }], + test2: { + test3: [{ + foo: '123' + }, { + foo: 'test1', + bar: 'testfailed' + }, { + foo: '123', + baz: { + test4: [{ + foo: 'test1', + baz: '123' + }] + } + }] + } + }; + + Joi.validate(input, schema, { abortEarly: false }, function (err, value) { + + expect(err).to.exist(); + expect(err.details).to.have.length(6); + expect(err.details).to.deep.equal([{ + message: '"foo" length must be less than or equal to 3 characters long', + path: 'test.0.foo', + type: 'string.max', + context: { limit: 3, value: 'test1', key: 'foo', encoding: undefined } + }, { + message: '"bar" length must be less than or equal to 5 characters long', + path: 'test.0.bar', + type: 'string.max', + context: { limit: 5, value: 'testfailed', key: 'bar', encoding: undefined } + }, { + message: '"foo" length must be less than or equal to 3 characters long', + path: 'test2.test3.1.foo', + type: 'string.max', + context: { limit: 3, value: 'test1', key: 'foo', encoding: undefined } + }, { + message: '"bar" length must be less than or equal to 5 characters long', + path: 'test2.test3.1.bar', + type: 'string.max', + context: { limit: 5, value: 'testfailed', key: 'bar', encoding: undefined } + }, { + message: '"foo" length must be less than or equal to 3 characters long', + path: 'test2.test3.2.baz.test4.0.foo', + type: 'string.max', + context: { limit: 3, value: 'test1', key: 'foo', encoding: undefined } + }, { + message: '"baz" is not allowed', + path: 'test2.test3.2.baz.test4.0.baz', + type: 'object.allowUnknown', + context: { key: 'baz' } + }]); + done(); + }); + }); + + it('validates using the root any object', function (done) { + + var any = Joi; + any.validate('abc', function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('validates using the root any object (no callback)', function (done) { + + var any = Joi; + var result = any.validate('abc'); + expect(result.error).to.not.exist(); + expect(result.value).to.equal('abc'); + done(); + }); + + it('accepts no options', function (done) { + + Joi.validate('test', Joi.string(), function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('accepts no options (no callback)', function (done) { + + var result = Joi.validate('test', Joi.string()); + expect(result.error).to.not.exist(); + expect(result.value).to.equal('test'); + done(); + }); + + it('accepts options', function (done) { + + Joi.validate('5', Joi.number(), { convert: false }, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('accepts options (no callback)', function (done) { + + var result = Joi.validate('5', Joi.number(), { convert: false }); + expect(result.error).to.exist(); + done(); + }); + + it('accepts null options', function (done) { + + Joi.validate('test', Joi.string(), null, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('accepts undefined options', function (done) { + + Joi.validate('test', Joi.string(), undefined, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + describe('#describe', function () { + + var defaultFn = function () { + + return 'test'; + }; + defaultFn.description = 'testing'; + + var defaultDescribedFn = function () { + + return 'test'; + }; + + var defaultRef = Joi.ref('xor'); + + var schema = Joi.object({ + sub: { + email: Joi.string().email(), + date: Joi.date(), + child: Joi.object({ + alphanum: Joi.string().alphanum() + }) + }, + min: [Joi.number(), Joi.string().min(3)], + max: Joi.string().max(3), + required: Joi.string().required(), + xor: Joi.string(), + renamed: Joi.string().valid('456'), + notEmpty: Joi.string().required().description('a').notes('b').tags('c'), + empty: Joi.string().empty('').strip(), + defaultRef: Joi.string().default(defaultRef, 'not here'), + defaultFn: Joi.string().default(defaultFn, 'not here'), + defaultDescribedFn: Joi.string().default(defaultDescribedFn, 'described test') + }).rename('renamed', 'required').without('required', 'xor').without('xor', 'required'); + + var result = { + type: 'object', + children: { + sub: { + type: 'object', + children: { + email: { + type: 'string', + invalids: [''], + rules: [{ name: 'email' }] + }, + date: { + type: 'date' + }, + child: { + type: 'object', + children: { + alphanum: { + type: 'string', + invalids: [''], + rules: [{ name: 'alphanum' }] + } + } + } + } + }, + min: { + type: 'alternatives', + alternatives: [ + { + type: 'number', + invalids: [Infinity, -Infinity] + }, + { + type: 'string', + invalids: [''], + rules: [{ name: 'min', arg: 3 }] + } + ] + }, + max: { + type: 'string', + invalids: [''], + rules: [{ name: 'max', arg: 3 }] + }, + required: { + type: 'string', + flags: { + presence: 'required' + }, + invalids: [''] + }, + xor: { + type: 'string', + invalids: [''] + }, + renamed: { + type: 'string', + flags: { + allowOnly: true + }, + valids: ['456'], + invalids: [''] + }, + notEmpty: { + type: 'string', + flags: { + presence: 'required' + }, + description: 'a', + notes: ['b'], + tags: ['c'], + invalids: [''] + }, + empty: { + type: 'string', + flags: { + empty: { + type: 'string', + flags: { + allowOnly: true + }, + valids: [''] + }, + strip: true + }, + invalids: [''] + }, + defaultRef: { + type: 'string', + flags: { + default: defaultRef + }, + invalids: [''] + }, + defaultFn: { + type: 'string', + flags: { + default: defaultFn + }, + invalids: [''] + }, + defaultDescribedFn: { + type: 'string', + flags: { + default: defaultDescribedFn + }, + invalids: [''] + } + }, + dependencies: [ + { + type: 'without', + key: 'required', + peers: ['xor'] + }, + { + type: 'without', + key: 'xor', + peers: ['required'] + } + ] + }; + + it('describes schema (direct)', function (done) { + + var description = schema.describe(); + expect(description).to.deep.equal(result); + expect(description.children.defaultRef.flags.default.description).to.not.exist(); + expect(description.children.defaultFn.flags.default.description).to.equal('testing'); + expect(description.children.defaultDescribedFn.flags.default.description).to.equal('described test'); + done(); + }); + + it('describes schema (root)', function (done) { + + var description = Joi.describe(schema); + expect(description).to.deep.equal(result); + done(); + }); + + it('describes schema (any)', function (done) { + + var any = Joi; + var description = any.describe(); + expect(description).to.deep.equal({ + type: 'any' + }); + done(); + }); + + it('describes schema without invalids', function (done) { + + var description = Joi.allow(null).describe(); + expect(description.invalids).to.not.exist(); + done(); + }); + }); + + describe('#assert', function () { + + it('does not have a return value', function (done) { + + var result; + expect(function () { + + result = Joi.assert('4', Joi.number()); + }).to.not.throw(); + expect(result).to.not.exist(); + done(); + }); + }); + + describe('#attempt', function () { + + it('throws on invalid value', function (done) { + + expect(function () { + + Joi.attempt('x', Joi.number()); + }).to.throw('"x"\n\u001b[31m\n[1] "value" must be a number\u001b[0m'); + done(); + }); + + it('does not throw on valid value', function (done) { + + expect(function () { + + Joi.attempt('4', Joi.number()); + }).to.not.throw(); + done(); + }); + + it('returns validated structure', function (done) { + + var valid; + expect(function () { + + valid = Joi.attempt('4', Joi.number()); + }).to.not.throw(); + expect(valid).to.equal(4); + done(); + }); + + it('throws on invalid value with message', function (done) { + + expect(function () { + + Joi.attempt('x', Joi.number(), 'the reason is'); + }).to.throw('the reason is "x"\n\u001b[31m\n[1] "value" must be a number\u001b[0m'); + done(); + }); + + it('throws on invalid value with message as error', function (done) { + + expect(function () { + + Joi.attempt('x', Joi.number(), new Error('invalid value')); + }).to.throw('invalid value'); + done(); + }); + }); + + describe('#compile', function () { + + it('throws an error on invalid value', function (done) { + + expect(function () { + + Joi.compile(undefined); + }).to.throw(Error, 'Invalid schema content: '); + done(); + }); + + it('shows path to errors in object', function (done) { + + var schema = { + a: { + b: { + c: { + d: undefined + } + } + } + }; + + expect(function () { + + Joi.compile(schema); + }).to.throw(Error, 'Invalid schema content: (a.b.c.d)'); + done(); + }); + }); +});
@@ -0,0 +1,834 @@
+// Load modules + +var Lab = require('lab'); +var Code = require('code'); +var Joi = require('../lib'); +var Helper = require('./helper'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +describe('number', function () { + + it('fails on boolean', function (done) { + + var schema = Joi.number(); + Helper.validate(schema, [ + [true, false], + [false, false] + ], done); + }); + + describe('#validate', function () { + + it('should, by default, allow undefined', function (done) { + + Helper.validate(Joi.number(), [ + [undefined, true] + ], done); + }); + + it('should, when .required(), deny undefined', function (done) { + + Helper.validate(Joi.number().required(), [ + [undefined, false] + ], done); + }); + + it('should return false for denied value', function (done) { + + var text = Joi.number().invalid(50); + text.validate(50, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('should validate integer', function (done) { + + var t = Joi.number().integer(); + Helper.validate(t, [ + [100, true], + [0, true], + [null, false], + [1.02, false], + [0.01, false] + ], done); + }); + + it('should return false for Infinity', function (done) { + + var t = Joi.number(); + Helper.validate(t, [ + [Infinity, false], + [-Infinity, false] + ], done); + }); + + it('should return true for allowed Infinity', function (done) { + + var t = Joi.number().allow(Infinity, -Infinity); + Helper.validate(t, [ + [Infinity, true], + [-Infinity, true] + ], done); + }); + + it('can accept string numbers', function (done) { + + var t = Joi.number(); + Helper.validate(t, [ + ['1', true], + ['100', true], + ['1e3', true], + ['1 some text', false], + ['\t\r', false], + [' ', false], + [' 2', true], + ['\t\r43', true], + ['43 ', true], + ['', false] + ], done); + }); + + it('required validates correctly', function (done) { + + var t = Joi.number().required(); + Helper.validate(t, [ + [NaN, false], + ['100', true] + ], done); + }); + + it('converts an object string to a number', function (done) { + + var config = { a: Joi.number() }; + var obj = { a: '123' }; + + Joi.compile(config).validate(obj, function (err, value) { + + expect(err).to.not.exist(); + expect(value.a).to.equal(123); + done(); + }); + }); + + it('converts a string to a number', function (done) { + + Joi.number().validate('1', function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.equal(1); + done(); + }); + }); + + it('errors on null', function (done) { + + Joi.number().validate(null, function (err, value) { + + expect(err).to.exist(); + expect(value).to.equal(null); + done(); + }); + }); + + it('should handle combination of min and max', function (done) { + + var rule = Joi.number().min(8).max(10); + Helper.validate(rule, [ + [1, false], + [11, false], + [8, true], + [9, true], + [null, false] + ], done); + }); + + it('should handle combination of min, max, and null allowed', function (done) { + + var rule = Joi.number().min(8).max(10).allow(null); + Helper.validate(rule, [ + [1, false], + [11, false], + [8, true], + [9, true], + [null, true] + ], done); + }); + + it('should handle combination of min and positive', function (done) { + + var rule = Joi.number().min(-3).positive(); + Helper.validate(rule, [ + [1, true], + [-2, false], + [8, true], + [null, false] + ], done); + }); + + it('should handle combination of max and positive', function (done) { + + var rule = Joi.number().max(5).positive(); + Helper.validate(rule, [ + [4, true], + [-2, false], + [8, false], + [null, false] + ], done); + }); + + it('should handle combination of min and negative', function (done) { + + var rule = Joi.number().min(-3).negative(); + Helper.validate(rule, [ + [4, false], + [-2, true], + [-4, false], + [null, false] + ], done); + }); + + it('should handle combination of negative and positive', function (done) { + + var rule = Joi.number().negative().positive(); + Helper.validate(rule, [ + [4, false], + [-2, false], + [0, false], + [null, false] + ], done); + }); + + it('should handle combination of negative and allow', function (done) { + + var rule = Joi.number().negative().allow(1); + Helper.validate(rule, [ + [1, true], + [-10, true], + [8, false], + [0, false], + [null, false] + ], done); + }); + + it('should handle combination of positive and allow', function (done) { + + var rule = Joi.number().positive().allow(-1); + Helper.validate(rule, [ + [1, true], + [-1, true], + [8, true], + [-10, false], + [null, false] + ], done); + }); + + it('should handle combination of positive, allow, and null allowed', function (done) { + + var rule = Joi.number().positive().allow(-1).allow(null); + Helper.validate(rule, [ + [1, true], + [-1, true], + [8, true], + [-10, false], + [null, true] + ], done); + }); + + it('should handle combination of negative, allow, and null allowed', function (done) { + + var rule = Joi.number().negative().allow(1).allow(null); + Helper.validate(rule, [ + [1, true], + [-10, true], + [8, false], + [0, false], + [null, true] + ], done); + }); + + it('should handle combination of positive, allow, null allowed, and invalid', function (done) { + + var rule = Joi.number().positive().allow(-1).allow(null).invalid(1); + Helper.validate(rule, [ + [1, false], + [-1, true], + [8, true], + [-10, false], + [null, true] + ], done); + }); + + it('should handle combination of negative, allow, null allowed, and invalid', function (done) { + + var rule = Joi.number().negative().allow(1).allow(null).invalid(-5); + Helper.validate(rule, [ + [1, true], + [-10, true], + [-5, false], + [8, false], + [0, false], + [null, true] + ], done); + }); + + it('should handle combination of min, max, and allow', function (done) { + + var rule = Joi.number().min(8).max(10).allow(1); + Helper.validate(rule, [ + [1, true], + [11, false], + [8, true], + [9, true], + [null, false] + ], done); + }); + + it('should handle combination of min, max, allow, and null allowed', function (done) { + + var rule = Joi.number().min(8).max(10).allow(1).allow(null); + Helper.validate(rule, [ + [1, true], + [11, false], + [8, true], + [9, true], + [null, true] + ], done); + }); + + it('should handle combination of min, max, allow, and invalid', function (done) { + + var rule = Joi.number().min(8).max(10).allow(1).invalid(9); + Helper.validate(rule, [ + [1, true], + [11, false], + [8, true], + [9, false], + [null, false] + ], done); + }); + + it('should handle combination of min, max, allow, invalid, and null allowed', function (done) { + + var rule = Joi.number().min(8).max(10).allow(1).invalid(9).allow(null); + Helper.validate(rule, [ + [1, true], + [11, false], + [8, true], + [9, false], + [null, true] + ], done); + }); + + it('should handle combination of min, max, and integer', function (done) { + + var rule = Joi.number().min(8).max(10).integer(); + Helper.validate(rule, [ + [1, false], + [11, false], + [8, true], + [9, true], + [9.1, false], + [null, false] + ], done); + }); + + it('should handle combination of min, max, integer, and allow', function (done) { + + var rule = Joi.number().min(8).max(10).integer().allow(9.1); + Helper.validate(rule, [ + [1, false], + [11, false], + [8, true], + [9, true], + [9.1, true], + [9.2, false], + [null, false] + ], done); + }); + + it('should handle combination of min, max, integer, allow, and invalid', function (done) { + + var rule = Joi.number().min(8).max(10).integer().allow(9.1).invalid(8); + Helper.validate(rule, [ + [1, false], + [11, false], + [8, false], + [9, true], + [9.1, true], + [9.2, false], + [null, false] + ], done); + }); + + it('should handle combination of min, max, integer, allow, invalid, and null allowed', function (done) { + + var rule = Joi.number().min(8).max(10).integer().allow(9.1).invalid(8).allow(null); + Helper.validate(rule, [ + [1, false], + [11, false], + [8, false], + [9, true], + [9.1, true], + [9.2, false], + [null, true] + ], done); + }); + + it('should handle limiting the number of decimal places', function (done) { + + var rule = Joi.number().precision(1).options({ convert: false }); + Helper.validate(rule, [ + [1, true], + [9.1, true], + [9.21, false], + [9.9999, false], + [9.999e99, true], + [9.9e-99, false], + [9.9e3, true], + [null, false] + ], done); + }); + + it('should handle combination of min, max, integer, allow, invalid, null allowed and precision', function (done) { + + var rule = Joi.number().min(8).max(10).integer().allow(9.1).invalid(8).allow(null).precision(1).options({ convert: false }); + Helper.validate(rule, [ + [1, false], + [11, false], + [8, false], + [9, true], + [9.1, true], + [9.11, false], + [9.2, false], + [9.22, false], + [null, true] + ], done); + }); + + it('should handle combination of greater and less', function (done) { + + var rule = Joi.number().greater(5).less(10); + Helper.validate(rule, [ + [0, false], + [11, false], + [5, false], + [10, false], + [8, true], + [5.01, true], + [9.99, true], + [null, false] + ], done); + }); + + it('should handle combination of greater, less, and integer', function (done) { + + var rule = Joi.number().integer().greater(5).less(10); + Helper.validate(rule, [ + [0, false], + [11, false], + [5, false], + [10, false], + [6, true], + [9, true], + [5.01, false], + [9.99, false] + ], done); + }); + + it('should handle combination of greater, less, and null allowed', function (done) { + + var rule = Joi.number().greater(5).less(10).allow(null); + Helper.validate(rule, [ + [0, false], + [11, false], + [5, false], + [10, false], + [8, true], + [5.01, true], + [9.99, true], + [null, true] + ], done); + }); + + it('should handle combination of greater, less, invalid, and allow', function (done) { + + var rule = Joi.number().greater(5).less(10).invalid(6).allow(-3); + Helper.validate(rule, [ + [0, false], + [11, false], + [5, false], + [10, false], + [6, false], + [8, true], + [5.01, true], + [9.99, true], + [-3, true], + [null, false] + ], done); + }); + }); + + it('should instantiate separate copies on invocation', function (done) { + + var result1 = Joi.number().min(5); + var result2 = Joi.number().max(5); + + expect(Object.keys(result1)).to.not.equal(Object.keys(result2)); + done(); + }); + + it('should show resulting object with #valueOf', function (done) { + + var result = Joi.number().min(5); + expect(result.valueOf()).to.exist(); + done(); + }); + + describe('error message', function () { + + it('should display correctly for int type', function (done) { + + var t = Joi.number().integer(); + Joi.compile(t).validate('1.1', function (err, value) { + + expect(err.message).to.contain('integer'); + done(); + }); + }); + }); + + describe('#min', function () { + + it('throws when limit is not a number', function (done) { + + expect(function () { + + Joi.number().min('a'); + }).to.throw('limit must be a number or reference'); + done(); + }); + + it('supports 64bit numbers', function (done) { + + var schema = Joi.number().min(1394035612500); + var input = 1394035612552; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.equal(input); + done(); + }); + }); + + it('accepts references as min value', function (done) { + + var schema = Joi.object({ a: Joi.number(), b: Joi.number().min(Joi.ref('a')) }); + + Helper.validate(schema, [ + [{ a: 42, b: 1337 }, true], + [{ a: 1337, b: 42 }, false], + [{ a: '1337', b: 42 }, false, null, 'child "b" fails because ["b" must be larger than or equal to 1337]'], + [{ a: 2.4, b: 4.2 }, true], + [{ a: 4.2, b: 4.20000001 }, true], + [{ a: 4.20000001, b: 4.2 }, false], + [{ a: 4.2, b: 2.4 }, false, null, 'child "b" fails because ["b" must be larger than or equal to 4.2]'] + ], done); + }); + + it('accepts context references as min value', function (done) { + + var schema = Joi.object({ b: Joi.number().min(Joi.ref('$a')) }); + + Helper.validate(schema, [ + [{ b: 1337 }, true, { context: { a: 42 } }], + [{ b: 42 }, false, { context: { a: 1337 } }], + [{ b: 4.2 }, true, { context: { a: 2.4 } }], + [{ b: 4.20000001 }, true, { context: { a: 4.2 } }], + [{ b: 4.2 }, false, { context: { a: 4.20000001 } }], + [{ b: 2.4 }, false, { context: { a: 4.2 } }, 'child "b" fails because ["b" must be larger than or equal to 4.2]'] + ], done); + }); + + it('errors if reference is not a number', function (done) { + + var schema = Joi.object({ a: Joi.string(), b: Joi.number().min(Joi.ref('a')) }); + + Helper.validate(schema, [ + [{ a: 'abc', b: 42 }, false, null, 'child "b" fails because ["b" references "a" which is not a number]'] + ], done); + }); + + it('errors if context reference is not a number', function (done) { + + var schema = Joi.object({ b: Joi.number().min(Joi.ref('$a')) }); + + Helper.validate(schema, [ + [{ b: 42 }, false, { context: { a: 'abc' } }, 'child "b" fails because ["b" references "a" which is not a number]'] + ], done); + }); + }); + + describe('#max', function () { + + it('throws when limit is not a number', function (done) { + + expect(function () { + + Joi.number().max('a'); + }).to.throw('limit must be a number or reference'); + done(); + }); + + it('accepts references as max value', function (done) { + + var schema = Joi.object({ a: Joi.number(), b: Joi.number().max(Joi.ref('a')) }); + + Helper.validate(schema, [ + [{ a: 1337, b: 42 }, true], + [{ a: 42, b: 1337 }, false], + [{ a: '42', b: 1337 }, false, null, 'child "b" fails because ["b" must be less than or equal to 42]'], + [{ a: 4.2, b: 2.4 }, true], + [{ a: 4.2, b: 4.20000001 }, false], + [{ a: 4.20000001, b: 4.2 }, true], + [{ a: 2.4, b: 4.2 }, false, null, 'child "b" fails because ["b" must be less than or equal to 2.4]'] + ], done); + }); + + it('accepts context references as max value', function (done) { + + var schema = Joi.object({ b: Joi.number().max(Joi.ref('$a')) }); + + Helper.validate(schema, [ + [{ b: 42 }, true, { context: { a: 1337 } }], + [{ b: 1337 }, false, { context: { a: 42 } }], + [{ b: 2.4 }, true, { context: { a: 4.2 } }], + [{ b: 4.20000001 }, false, { context: { a: 4.2 } }], + [{ b: 4.2 }, true, { context: { a: 4.20000001 } }], + [{ b: 4.2 }, false, { context: { a: 2.4 } }, 'child "b" fails because ["b" must be less than or equal to 2.4]'] + ], done); + }); + + it('errors if reference is not a number', function (done) { + + var schema = Joi.object({ a: Joi.string(), b: Joi.number().max(Joi.ref('a')) }); + + Helper.validate(schema, [ + [{ a: 'abc', b: 42 }, false, null, 'child "b" fails because ["b" references "a" which is not a number]'] + ], done); + }); + + it('errors if context reference is not a number', function (done) { + + var schema = Joi.object({ b: Joi.number().max(Joi.ref('$a')) }); + + Helper.validate(schema, [ + [{ b: 42 }, false, { context: { a: 'abc' } }, 'child "b" fails because ["b" references "a" which is not a number]'] + ], done); + }); + }); + + describe('#less', function () { + + it('throws when limit is not a number', function (done) { + + expect(function () { + + Joi.number().less('a'); + }).to.throw('limit must be a number or reference'); + done(); + }); + + it('accepts references as less value', function (done) { + + var schema = Joi.object({ a: Joi.number(), b: Joi.number().less(Joi.ref('a')) }); + + Helper.validate(schema, [ + [{ a: 1337, b: 42 }, true], + [{ a: 42, b: 1337 }, false], + [{ a: '42', b: 1337 }, false, null, 'child "b" fails because ["b" must be less than 42]'], + [{ a: 4.2, b: 2.4 }, true], + [{ a: 4.2, b: 4.20000001 }, false], + [{ a: 4.20000001, b: 4.2 }, true], + [{ a: 2.4, b: 4.2 }, false, null, 'child "b" fails because ["b" must be less than 2.4]'] + ], done); + }); + + it('accepts context references as less value', function (done) { + + var schema = Joi.object({ b: Joi.number().less(Joi.ref('$a')) }); + + Helper.validate(schema, [ + [{ b: 42 }, true, { context: { a: 1337 } }], + [{ b: 1337 }, false, { context: { a: 42 } }], + [{ b: 2.4 }, true, { context: { a: 4.2 } }], + [{ b: 4.20000001 }, false, { context: { a: 4.2 } }], + [{ b: 4.2 }, true, { context: { a: 4.20000001 } }], + [{ b: 4.2 }, false, { context: { a: 2.4 } }, 'child "b" fails because ["b" must be less than 2.4]'] + ], done); + }); + + it('errors if reference is not a number', function (done) { + + var schema = Joi.object({ a: Joi.string(), b: Joi.number().less(Joi.ref('a')) }); + + Helper.validate(schema, [ + [{ a: 'abc', b: 42 }, false, null, 'child "b" fails because ["b" references "a" which is not a number]'] + ], done); + }); + + it('errors if context reference is not a number', function (done) { + + var schema = Joi.object({ a: Joi.string(), b: Joi.number().less(Joi.ref('$a')) }); + + Helper.validate(schema, [ + [{ b: 42 }, false, { context: { a: 'abc' } }, 'child "b" fails because ["b" references "a" which is not a number]'] + ], done); + }); + }); + + describe('#greater', function () { + + it('throws when limit is not a number', function (done) { + + expect(function () { + + Joi.number().greater('a'); + }).to.throw('limit must be a number or reference'); + done(); + }); + + it('accepts references as greater value', function (done) { + + var schema = Joi.object({ a: Joi.number(), b: Joi.number().greater(Joi.ref('a')) }); + + Helper.validate(schema, [ + [{ a: 42, b: 1337 }, true], + [{ a: 1337, b: 42 }, false], + [{ a: '1337', b: 42 }, false, null, 'child "b" fails because ["b" must be greater than 1337]'], + [{ a: 2.4, b: 4.2 }, true], + [{ a: 4.2, b: 4.20000001 }, true], + [{ a: 4.20000001, b: 4.2 }, false], + [{ a: 4.2, b: 2.4 }, false, null, 'child "b" fails because ["b" must be greater than 4.2]'] + ], done); + }); + + it('accepts context references as greater value', function (done) { + + var schema = Joi.object({ b: Joi.number().greater(Joi.ref('$a')) }); + + Helper.validate(schema, [ + [{ b: 1337 }, true, { context: { a: 42 } }], + [{ b: 42 }, false, { context: { a: 1337 } }], + [{ b: 4.2 }, true, { context: { a: 2.4 } }], + [{ b: 4.20000001 }, true, { context: { a: 4.2 } }], + [{ b: 4.2 }, false, { context: { a: 4.20000001 } }], + [{ b: 2.4 }, false, { context: { a: 4.2 } }, 'child "b" fails because ["b" must be greater than 4.2]'] + ], done); + }); + + it('errors if reference is not a number', function (done) { + + var schema = Joi.object({ a: Joi.string(), b: Joi.number().greater(Joi.ref('a')) }); + + Helper.validate(schema, [ + [{ a: 'abc', b: 42 }, false, null, 'child "b" fails because ["b" references "a" which is not a number]'] + ], done); + }); + + it('errors if context reference is not a number', function (done) { + + var schema = Joi.object({ b: Joi.number().greater(Joi.ref('$a')) }); + + Helper.validate(schema, [ + [{ b: 42 }, false, { context: { a: 'abc' } }, 'child "b" fails because ["b" references "a" which is not a number]'] + ], done); + }); + }); + + describe('#precision', function () { + + it('converts numbers', function (done) { + + var rule = Joi.number().precision(4); + Helper.validate(rule, [ + [1.5, true, null, 1.5], + [0.12345, true, null, 0.1235], + [123456, true, null, 123456], + [123456.123456, true, null, 123456.1235], + ['123456.123456', true, null, 123456.1235], + ['abc', false], + [NaN, false] + ], done); + }); + }); + + describe('#describe', function () { + + it('should describe a minimum of 0', function (done) { + + var schema = Joi.number().min(0); + expect(schema.describe()).to.deep.equal({ + type: 'number', + invalids: [Infinity, -Infinity], + rules: [ + { + name: 'min', + arg: 0 + } + ] + }); + done(); + }); + }); + + describe('#multiple', function () { + + it('throws when multiple is not a number', function (done) { + + expect(function () { + + Joi.number().multiple('a'); + }).to.throw('multiple must be an integer'); + done(); + }); + + it('throws when multiple is 0', function (done) { + + expect(function () { + + Joi.number().multiple(0); + }).to.throw('multiple must be greater than 0'); + done(); + }); + + it('should handle multiples correctly', function (done) { + + var rule = Joi.number().multiple(3); + Helper.validate(rule, [ + [0, true], // 0 is a multiple of every integer + [3, true], + [4, false], + [9, true], + ['a', false], + [9.1, false], + [8.9, false] + ], done); + }); + }); +});
@@ -0,0 +1,1309 @@
+// Load modules + +var Lab = require('lab'); +var Code = require('code'); +var Joi = require('../lib'); +var Helper = require('./helper'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +describe('object', function () { + + it('converts a json string to an object', function (done) { + + Joi.object().validate('{"hi":true}', function (err, value) { + + expect(err).to.not.exist(); + expect(value.hi).to.equal(true); + done(); + }); + }); + + it('errors on non-object string', function (done) { + + Joi.object().validate('a string', function (err, value) { + + expect(err).to.exist(); + expect(value).to.equal('a string'); + done(); + }); + }); + + it('validates an object', function (done) { + + var schema = Joi.object().required(); + Helper.validate(schema, [ + [{}, true], + [{ hi: true }, true], + ['', false] + ], done); + }); + + it('return object reference when no rules specified', function (done) { + + var schema = Joi.object({ + a: Joi.object() + }); + + var item = { x: 5 }; + schema.validate({ a: item }, function (err, value) { + + expect(value.a).to.equal(item); + done(); + }); + }); + + it('retains ignored values', function (done) { + + var schema = Joi.object(); + schema.validate({ a: 5 }, function (err, value) { + + expect(value.a).to.equal(5); + done(); + }); + }); + + it('retains skipped values', function (done) { + + var schema = Joi.object({ b: 5 }).unknown(true); + schema.validate({ b: '5', a: 5 }, function (err, value) { + + expect(value.a).to.equal(5); + expect(value.b).to.equal(5); + done(); + }); + }); + + it('allows any key when schema is undefined', function (done) { + + Joi.object().validate({ a: 4 }, function (err, value) { + + expect(err).to.not.exist(); + + Joi.object(undefined).validate({ a: 4 }, function (err2, value2) { + + expect(err2).to.not.exist(); + done(); + }); + }); + }); + + it('allows any key when schema is null', function (done) { + + Joi.object(null).validate({ a: 4 }, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('throws on invalid object schema', function (done) { + + expect(function () { + + Joi.object(4); + }).to.throw('Object schema must be a valid object'); + done(); + }); + + it('throws on joi object schema', function (done) { + + expect(function () { + + Joi.object(Joi.object()); + }).to.throw('Object schema cannot be a joi schema'); + done(); + }); + + it('skips conversion when value is undefined', function (done) { + + Joi.object({ a: Joi.object() }).validate(undefined, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.not.exist(); + done(); + }); + }); + + it('errors on array', function (done) { + + Joi.object().validate([1, 2, 3], function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('should prevent extra keys from existing by default', function (done) { + + var schema = Joi.object({ item: Joi.string().required() }).required(); + Helper.validate(schema, [ + [{ item: 'something' }, true], + [{ item: 'something', item2: 'something else' }, false], + ['', false] + ], done); + }); + + it('should validate count when min is set', function (done) { + + var schema = Joi.object().min(3); + Helper.validate(schema, [ + [{ item: 'something' }, false], + [{ item: 'something', item2: 'something else' }, false], + [{ item: 'something', item2: 'something else', item3: 'something something else' }, true], + ['', false] + ], done); + }); + + it('should validate count when max is set', function (done) { + + var schema = Joi.object().max(2); + Helper.validate(schema, [ + [{ item: 'something' }, true], + [{ item: 'something', item2: 'something else' }, true], + [{ item: 'something', item2: 'something else', item3: 'something something else' }, false], + ['', false] + ], done); + }); + + it('should validate count when min and max is set', function (done) { + + var schema = Joi.object().max(3).min(2); + Helper.validate(schema, [ + [{ item: 'something' }, false], + [{ item: 'something', item2: 'something else' }, true], + [{ item: 'something', item2: 'something else', item3: 'something something else' }, true], + [{ item: 'something', item2: 'something else', item3: 'something something else', item4: 'item4' }, false], + ['', false] + ], done); + }); + + it('should validate count when length is set', function (done) { + + var schema = Joi.object().length(2); + Helper.validate(schema, [ + [{ item: 'something' }, false], + [{ item: 'something', item2: 'something else' }, true], + [{ item: 'something', item2: 'something else', item3: 'something something else' }, false], + ['', false] + ], done); + }); + + it('should validate constructor when type is set', function (done) { + + var schema = Joi.object().type(RegExp); + Helper.validate(schema, [ + [{ item: 'something' }, false], + ['', false], + [new Date(), false], + [/abcd/, true], + [new RegExp(), true] + ], done); + }); + + it('should traverse an object and validate all properties in the top level', function (done) { + + var schema = Joi.object({ + num: Joi.number() + }); + + Helper.validate(schema, [ + [{ num: 1 }, true], + [{ num: [1, 2, 3] }, false] + ], done); + }); + + it('should traverse an object and child objects and validate all properties', function (done) { + + var schema = Joi.object({ + num: Joi.number(), + obj: Joi.object({ + item: Joi.string() + }) + }); + + Helper.validate(schema, [ + [{ num: 1 }, true], + [{ num: [1, 2, 3] }, false], + [{ num: 1, obj: { item: 'something' } }, true], + [{ num: 1, obj: { item: 123 } }, false] + ], done); + }); + + it('should traverse an object several levels', function (done) { + + var schema = Joi.object({ + obj: Joi.object({ + obj: Joi.object({ + obj: Joi.object({ + item: Joi.boolean() + }) + }) + }) + }); + + Helper.validate(schema, [ + [{ num: 1 }, false], + [{ obj: {} }, true], + [{ obj: { obj: {} } }, true], + [{ obj: { obj: { obj: {} } } }, true], + [{ obj: { obj: { obj: { item: true } } } }, true], + [{ obj: { obj: { obj: { item: 10 } } } }, false] + ], done); + }); + + it('should traverse an object several levels with required levels', function (done) { + + var schema = Joi.object({ + obj: Joi.object({ + obj: Joi.object({ + obj: Joi.object({ + item: Joi.boolean() + }) + }).required() + }) + }); + + Helper.validate(schema, [ + [null, false], + [undefined, true], + [{}, true], + [{ obj: {} }, false], + [{ obj: { obj: {} } }, true], + [{ obj: { obj: { obj: {} } } }, true], + [{ obj: { obj: { obj: { item: true } } } }, true], + [{ obj: { obj: { obj: { item: 10 } } } }, false] + ], done); + }); + + it('should traverse an object several levels with required levels (without Joi.obj())', function (done) { + + var schema = { + obj: { + obj: { + obj: { + item: Joi.boolean().required() + } + } + } + }; + + Helper.validate(schema, [ + [null, false], + [undefined, true], + [{}, true], + [{ obj: {} }, true], + [{ obj: { obj: {} } }, true], + [{ obj: { obj: { obj: {} } } }, false], + [{ obj: { obj: { obj: { item: true } } } }, true], + [{ obj: { obj: { obj: { item: 10 } } } }, false] + ], done); + }); + + it('errors on unknown keys when functions allows', function (done) { + + var schema = Joi.object({ a: Joi.number() }).options({ skipFunctions: true }); + var obj = { a: 5, b: 'value' }; + schema.validate(obj, function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('validates both valid() and with()', function (done) { + + var schema = Joi.object({ + first: Joi.valid('value'), + second: Joi.any() + }).with('first', 'second'); + + Helper.validate(schema, [ + [{ first: 'value' }, false] + ], done); + }); + + it('validates referenced arrays in valid()', function (done) { + + var schema = Joi.object({ + foo: Joi.valid(Joi.ref('$x')) + }); + + Helper.validate(schema, [ + [{ foo: 'bar' }, true, { context: { x: 'bar' } }], + [{ foo: 'bar' }, true, { context: { x: ['baz', 'bar'] } }], + [{ foo: 'bar' }, false, { context: { x: 'baz' } }], + [{ foo: 'bar' }, false, { context: { x: ['baz', 'qux'] } }], + [{ foo: 'bar' }, false] + ], done); + }); + + it('errors on unknown nested keys with the correct path', function (done) { + + var schema = Joi.object({ a: Joi.object().keys({}) }); + var obj = { a: { b: 'value' } }; + schema.validate(obj, function (err, value) { + + expect(err).to.exist(); + expect(err.details[0].path).to.equal('a.b'); + done(); + }); + }); + + it('errors on unknown nested keys with the correct path at the root level', function (done) { + + var schema = Joi.object({ a: Joi.object().keys({}) }); + var obj = { c: 'hello' }; + schema.validate(obj, function (err, value) { + + expect(err).to.exist(); + expect(err.details[0].path).to.equal('c'); + done(); + }); + }); + + it('should work on prototype-less objects', function (done) { + + var input = Object.create(null); + var schema = Joi.object().keys({ + a: Joi.number() + }); + + input.a = 1337; + + Joi.validate(input, schema, function (err) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('should be able to use rename safely with a fake hasOwnProperty', function (done) { + + var input = { a: 1, hasOwnProperty: 'foo' }; + var schema = Joi.object().rename('b', 'a'); + + Joi.validate(input, schema, function (err) { + + expect(err.message).to.equal('"value" cannot rename child "b" because override is disabled and target "a" exists'); + done(); + }); + }); + + it('should be able to use object.with() safely with a fake hasOwnProperty', function (done) { + + var input = { a: 1, hasOwnProperty: 'foo' }; + var schema = Joi.object({ a: 1 }).with('a', 'b'); + + Joi.validate(input, schema, function (err) { + + expect(err.message).to.equal('"hasOwnProperty" is not allowed. "a" missing required peer "b"'); + done(); + }); + }); + + describe('#keys', function () { + + it('allows any key', function (done) { + + var a = Joi.object({ a: 4 }); + var b = a.keys(); + a.validate({ b: 3 }, function (err, value) { + + expect(err).to.exist(); + b.validate({ b: 3 }, function (err2, value2) { + + expect(err2).to.not.exist(); + done(); + }); + }); + }); + + it('forbids all keys', function (done) { + + var a = Joi.object(); + var b = a.keys({}); + a.validate({ b: 3 }, function (err, value) { + + expect(err).to.not.exist(); + b.validate({ b: 3 }, function (err2, value2) { + + expect(err2).to.exist(); + done(); + }); + }); + }); + + it('adds to existing keys', function (done) { + + var a = Joi.object({ a: 1 }); + var b = a.keys({ b: 2 }); + a.validate({ a: 1, b: 2 }, function (err, value) { + + expect(err).to.exist(); + b.validate({ a: 1, b: 2 }, function (err2, value2) { + + expect(err2).to.not.exist(); + done(); + }); + }); + }); + + it('overrides existing keys', function (done) { + + var a = Joi.object({ a: 1 }); + var b = a.keys({ a: Joi.string() }); + + Helper.validate(a, [ + [{ a: 1 }, true, null, { a: 1 }], + [{ a: '1' }, true, null, { a: 1 }], + [{ a: '2' }, false, null, 'child "a" fails because ["a" must be one of [1]]'] + ], function () { + + Helper.validate(b, [ + [{ a: 1 }, false, null, 'child "a" fails because ["a" must be a string]'], + [{ a: '1' }, true, null, { a: '1' }] + ], done); + }); + }); + + it('strips keys flagged with strip', function (done) { + + var schema = Joi.object({ + a: Joi.string().strip(), + b: Joi.string() + }); + schema.validate({ a: 'test', b: 'test' }, function (err, value) { + + expect(err).to.not.exist(); + expect(value.a).to.not.exist(); + expect(value.b).to.equal('test'); + done(); + }); + }); + + it('does not alter the original object when stripping keys', function (done) { + + var schema = Joi.object({ + a: Joi.string().strip(), + b: Joi.string() + }); + + var valid = { + a: 'test', + b: 'test' + }; + + schema.validate(valid, function (err, value) { + + expect(err).to.not.exist(); + expect(value.a).to.not.exist(); + expect(valid.a).to.equal('test'); + expect(value.b).to.equal('test'); + expect(valid.b).to.equal('test'); + done(); + }); + }); + + it('should strip from an alternative', function (done) { + + var schema = Joi.object({ + a: [Joi.boolean().strip()] + }); + + var valid = { + a: true + }; + + schema.validate(valid, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal({}); + done(); + }); + }); + }); + + describe('#unknown', function () { + + it('allows local unknown without applying to children', function (done) { + + var schema = Joi.object({ + a: { + b: Joi.number() + } + }).unknown(); + + Helper.validate(schema, [ + [{ a: { b: 5 } }, true], + [{ a: { b: 'x' } }, false], + [{ a: { b: 5 }, c: 'ignore' }, true], + [{ a: { b: 5, c: 'ignore' } }, false] + ], done); + }); + + it('forbids local unknown without applying to children', function (done) { + + var schema = Joi.object({ + a: Joi.object({ + b: Joi.number() + }).unknown() + }).options({ allowUnknown: false }); + + Helper.validate(schema, [ + [{ a: { b: 5 } }, true], + [{ a: { b: 'x' } }, false], + [{ a: { b: 5 }, c: 'ignore' }, false], + [{ a: { b: 5, c: 'ignore' } }, true] + ], done); + }); + }); + + describe('#rename', function () { + + it('allows renaming multiple times with multiple enabled', function (done) { + + var schema = Joi.object({ + test: Joi.string() + }).rename('test1', 'test').rename('test2', 'test', { multiple: true }); + + Joi.compile(schema).validate({ test1: 'a', test2: 'b' }, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('errors renaming multiple times with multiple disabled', function (done) { + + var schema = Joi.object({ + test: Joi.string() + }).rename('test1', 'test').rename('test2', 'test'); + + Joi.compile(schema).validate({ test1: 'a', test2: 'b' }, function (err, value) { + + expect(err.message).to.equal('"value" cannot rename child "test2" because multiple renames are disabled and another key was already renamed to "test"'); + done(); + }); + }); + + it('errors multiple times when abortEarly is false', function (done) { + + Joi.object().rename('a', 'b').rename('c', 'b').rename('d', 'b').options({ abortEarly: false }).validate({ a: 1, c: 1, d: 1 }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" cannot rename child "c" because multiple renames are disabled and another key was already renamed to "b". "value" cannot rename child "d" because multiple renames are disabled and another key was already renamed to "b"'); + done(); + }); + }); + + it('aliases a key', function (done) { + + var schema = Joi.object({ + a: Joi.number(), + b: Joi.number() + }).rename('a', 'b', { alias: true }); + + var obj = { a: 10 }; + + Joi.compile(schema).validate(obj, function (err, value) { + + expect(err).to.not.exist(); + expect(value.a).to.equal(10); + expect(value.b).to.equal(10); + done(); + }); + }); + + it('with override disabled should not allow overwriting existing value', function (done) { + + var schema = Joi.object({ + test1: Joi.string() + }).rename('test', 'test1'); + + schema.validate({ test: 'b', test1: 'a' }, function (err, value) { + + expect(err.message).to.equal('"value" cannot rename child "test" because override is disabled and target "test1" exists'); + done(); + }); + }); + + it('with override enabled should allow overwriting existing value', function (done) { + + var schema = Joi.object({ + test1: Joi.string() + }).rename('test', 'test1', { override: true }); + + schema.validate({ test: 'b', test1: 'a' }, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('renames when data is nested in an array via items', function (done) { + + var schema = { + arr: Joi.array().items(Joi.object({ + one: Joi.string(), + two: Joi.string() + }).rename('uno', 'one').rename('dos', 'two')) + }; + + var data = { arr: [{ uno: '1', dos: '2' }] }; + Joi.object(schema).validate(data, function (err, value) { + + expect(err).to.not.exist(); + expect(value.arr[0].one).to.equal('1'); + expect(value.arr[0].two).to.equal('2'); + done(); + }); + }); + + it('applies rename and validation in the correct order regardless of key order', function (done) { + + var schema1 = Joi.object({ + a: Joi.number() + }).rename('b', 'a'); + + var input1 = { b: '5' }; + + schema1.validate(input1, function (err1, value1) { + + expect(err1).to.not.exist(); + expect(value1.b).to.not.exist(); + expect(value1.a).to.equal(5); + + var schema2 = Joi.object({ a: Joi.number(), b: Joi.any() }).rename('b', 'a'); + var input2 = { b: '5' }; + + schema2.validate(input2, function (err2, value2) { + + expect(err2).to.not.exist(); + expect(value2.b).to.not.exist(); + expect(value2.a).to.equal(5); + + done(); + }); + }); + }); + + it('sets the default value after key is renamed', function (done) { + + var schema = Joi.object({ + foo2: Joi.string().default('test') + }).rename('foo', 'foo2'); + + var input = {}; + + Joi.validate(input, schema, function (err, value) { + + expect(err).to.not.exist(); + expect(value.foo2).to.equal('test'); + + done(); + }); + }); + + it('should be able to rename keys that are empty strings', function (done) { + + var schema = Joi.object().rename('', 'notEmpty'); + var input = { + '': 'something' + }; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value['']).to.not.exist(); + expect(value.notEmpty).to.equal('something'); + done(); + }); + }); + + it('should not create new keys when they key in question does not exist', function (done) { + + var schema = Joi.object().rename('b', '_b'); + + var input = { + a: 'something' + }; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(Object.keys(value)).to.include('a'); + expect(value.a).to.equal('something'); + done(); + }); + }); + + it('should remove a key with override if from does not exist', function (done) { + + var schema = Joi.object().rename('b', 'a', { override: true }); + + var input = { + a: 'something' + }; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal({}); + done(); + }); + }); + + it('should ignore a key with ignoredUndefined if from does not exist', function (done){ + + var schema = Joi.object().rename('b', 'a', { ignoreUndefined: true }); + + var input = { + a: 'something' + }; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal({ a: 'something' }); + done(); + }); + }); + + it('shouldn\'t delete a key with override and ignoredUndefined if from does not exist', function (done){ + + var schema = Joi.object().rename('b', 'a', { ignoreUndefined: true, override: true }); + + var input = { + a: 'something' + }; + + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal({ a: 'something' }); + done(); + }); + }); + }); + + describe('#describe', function () { + + it('return empty description when no schema defined', function (done) { + + var schema = Joi.object(); + var desc = schema.describe(); + expect(desc).to.deep.equal({ + type: 'object' + }); + done(); + }); + + it('respects the shallow parameter', function (done) { + + var schema = Joi.object({ + name: Joi.string(), + child: Joi.object({ + name: Joi.string() + }) + }); + + expect(Object.keys(schema.describe(true))).to.not.include('children'); + expect(Object.keys(schema.describe())).to.include('children'); + + done(); + }); + + it('describes patterns', function (done) { + + var schema = Joi.object({ + a: Joi.string() + }).pattern(/\w\d/i, Joi.boolean()); + + expect(schema.describe()).to.deep.equal({ + type: 'object', + children: { + a: { + type: 'string', + invalids: [''] + } + }, + patterns: [ + { + regex: '/\\w\\d/i', + rule: { + type: 'boolean' + } + } + ] + }); + + done(); + }); + }); + + describe('#length', function () { + + it('throws when length is not a number', function (done) { + + expect(function () { + + Joi.object().length('a'); + }).to.throw('limit must be a positive integer'); + done(); + }); + }); + + describe('#min', function () { + + it('throws when limit is not a number', function (done) { + + expect(function () { + + Joi.object().min('a'); + }).to.throw('limit must be a positive integer'); + done(); + }); + }); + + describe('#max', function () { + + it('throws when limit is not a number', function (done) { + + expect(function () { + + Joi.object().max('a'); + }).to.throw('limit must be a positive integer'); + done(); + }); + }); + + describe('#pattern', function () { + + it('shows path to errors in schema', function (done) { + + expect(function () { + + Joi.object().pattern(/.*/, { + a: { + b: { + c: { + d: undefined + } + } + } + }); + }).to.throw(Error, 'Invalid schema content: (a.b.c.d)'); + + expect(function () { + + Joi.object().pattern(/.*/, function () { + + }); + }).to.throw(Error, 'Invalid schema content: '); + + done(); + }); + + it('validates unknown keys using a pattern', function (done) { + + var schema = Joi.object({ + a: Joi.number() + }).pattern(/\d+/, Joi.boolean()).pattern(/\w\w+/, 'x'); + + Joi.validate({ bb: 'y', 5: 'x' }, schema, { abortEarly: false }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('child "5" fails because ["5" must be a boolean]. child "bb" fails because ["bb" must be one of [x]]'); + + Helper.validate(schema, [ + [{ a: 5 }, true], + [{ a: 'x' }, false], + [{ b: 'x' }, false], + [{ bb: 'x' }, true], + [{ 5: 'x' }, false], + [{ 5: false }, true], + [{ 5: undefined }, true] + ], done); + }); + }); + + it('validates unknown keys using a pattern (nested)', function (done) { + + var schema = { + x: Joi.object({ + a: Joi.number() + }).pattern(/\d+/, Joi.boolean()).pattern(/\w\w+/, 'x') + }; + + Joi.validate({ x: { bb: 'y', 5: 'x' } }, schema, { abortEarly: false }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('child "x" fails because [child "5" fails because ["5" must be a boolean], child "bb" fails because ["bb" must be one of [x]]]'); + done(); + }); + }); + + it('errors when using a pattern on empty schema with unknown(false) and pattern mismatch', function (done) { + + var schema = Joi.object().pattern(/\d/, Joi.number()).unknown(false); + + Joi.validate({ a: 5 }, schema, { abortEarly: false }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"a" is not allowed'); + done(); + }); + }); + + it('removes global flag from patterns', function (done) { + + var schema = Joi.object().pattern(/a/g, Joi.number()); + + Joi.validate({ a1: 5, a2: 6 }, schema, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + }); + + describe('#with', function () { + + it('should throw an error when a parameter is not a string', function (done) { + + try { + Joi.object().with({}); + var error = false; + } + catch (e) { + error = true; + } + expect(error).to.equal(true); + + try { + Joi.object().with(123); + error = false; + } + catch (e) { + error = true; + } + expect(error).to.equal(true); + done(); + }); + + it('should validate correctly when key is an empty string', function (done) { + + var schema = Joi.object().with('', 'b'); + Helper.validate(schema, [ + [{ c: 'hi', d: 'there' }, true] + ]); + done(); + }); + }); + + describe('#without', function () { + + it('should throw an error when a parameter is not a string', function (done) { + + try { + Joi.object().without({}); + var error = false; + } + catch (e) { + error = true; + } + expect(error).to.equal(true); + + try { + Joi.object().without(123); + error = false; + } + catch (e) { + error = true; + } + expect(error).to.equal(true); + + + done(); + }); + + it('should validate correctly when key is an empty string', function (done) { + + var schema = Joi.object().without('', 'b'); + Helper.validate(schema, [ + [{ a: 'hi', b: 'there' }, true] + ]); + done(); + }); + }); + + describe('#xor', function () { + + it('should throw an error when a parameter is not a string', function (done) { + + try { + Joi.object().xor({}); + var error = false; + } + catch (e) { + error = true; + } + expect(error).to.equal(true); + + try { + Joi.object().xor(123); + error = false; + } + catch (e) { + error = true; + } + expect(error).to.equal(true); + done(); + }); + }); + + describe('#or', function () { + + it('should throw an error when a parameter is not a string', function (done) { + + try { + Joi.object().or({}); + var error = false; + } + catch (e) { + error = true; + } + expect(error).to.equal(true); + + try { + Joi.object().or(123); + error = false; + } + catch (e) { + error = true; + } + expect(error).to.equal(true); + done(); + }); + + it('errors multiple levels deep', function (done) { + + Joi.object({ + a: { + b: Joi.object().or('x', 'y') + } + }).validate({ a: { b: { c: 1 } } }, function (err, value) { + + expect(err).to.exist(); + expect(err.details[0].path).to.equal('a.b'); + expect(err.message).to.equal('child "a" fails because [child "b" fails because ["value" must contain at least one of [x, y]]]'); + done(); + }); + }); + }); + + describe('#assert', function () { + + it('shows path to errors in schema', function (done) { + + expect(function () { + + Joi.object().assert('a.b', { + a: { + b: { + c: { + d: undefined + } + } + } + }); + }).to.throw(Error, 'Invalid schema content: (a.b.c.d)'); + done(); + }); + + it('shows errors in schema', function (done) { + + expect(function () { + + Joi.object().assert('a.b', undefined); + }).to.throw(Error, 'Invalid schema content: '); + done(); + }); + + it('validates upwards reference', function (done) { + + var schema = Joi.object({ + a: { + b: Joi.string(), + c: Joi.number() + }, + d: { + e: Joi.any() + } + }).assert(Joi.ref('d/e', { separator: '/' }), Joi.ref('a.c'), 'equal to a.c'); + + schema.validate({ a: { b: 'x', c: 5 }, d: { e: 6 } }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"d.e" validation failed because "d.e" failed to equal to a.c'); + + Helper.validate(schema, [ + [{ a: { b: 'x', c: 5 }, d: { e: 5 } }, true] + ], done); + }); + }); + + it('validates upwards reference with implicit context', function (done) { + + var schema = Joi.object({ + a: { + b: Joi.string(), + c: Joi.number() + }, + d: { + e: Joi.any() + } + }).assert('d.e', Joi.ref('a.c'), 'equal to a.c'); + + schema.validate({ a: { b: 'x', c: 5 }, d: { e: 6 } }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('"d.e" validation failed because "d.e" failed to equal to a.c'); + + Helper.validate(schema, [ + [{ a: { b: 'x', c: 5 }, d: { e: 5 } }, true] + ], done); + }); + }); + + it('throws when context is at root level', function (done) { + + expect(function () { + + Joi.object({ + a: { + b: Joi.string(), + c: Joi.number() + }, + d: { + e: Joi.any() + } + }).assert('a', Joi.ref('d.e'), 'equal to d.e'); + }).to.throw('Cannot use assertions for root level references - use direct key rules instead'); + done(); + }); + + it('allows root level context ref', function (done) { + + expect(function () { + + Joi.object({ + a: { + b: Joi.string(), + c: Joi.number() + }, + d: { + e: Joi.any() + } + }).assert('$a', Joi.ref('d.e'), 'equal to d.e'); + }).to.not.throw(); + done(); + }); + + it('provides a default message for failed assertions', function (done) { + + var schema = Joi.object({ + a: { + b: Joi.string(), + c: Joi.number() + }, + d: { + e: Joi.any() + } + }).assert('d.e', Joi.boolean()); + + schema.validate({ + d: { + e: [] + } + }, function (err) { + + expect(err).to.exist(); + expect(err.message).to.equal('"d.e" validation failed because "d.e" failed to pass the assertion test'); + done(); + }); + }); + }); + + describe('#type', function () { + + it('uses constructor name for default type name', function (done) { + + var Foo = function Foo () {}; + + var schema = Joi.object().type(Foo); + schema.validate({}, function (err) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" must be an instance of "Foo"'); + done(); + }); + }); + + it('uses custom type name if supplied', function (done) { + + var Foo = function () {}; + + var schema = Joi.object().type(Foo, 'Bar'); + schema.validate({}, function (err) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" must be an instance of "Bar"'); + done(); + }); + }); + + it('overrides constructor name with custom name', function (done) { + + var Foo = function Foo () {}; + + var schema = Joi.object().type(Foo, 'Bar'); + schema.validate({}, function (err) { + + expect(err).to.exist(); + expect(err.message).to.equal('"value" must be an instance of "Bar"'); + done(); + }); + }); + + it('throws when constructor is not a function', function (done) { + + expect(function () { + + Joi.object().type(''); + }).to.throw('type must be a constructor function'); + done(); + }); + + it('uses the constructor name in the schema description', function (done) { + + var description = Joi.object().type(RegExp).describe(); + + expect(description.rules).to.deep.include({ name: 'type', arg: 'RegExp' }); + done(); + }); + }); +});
@@ -0,0 +1,387 @@
+// Load modules + +var Lab = require('lab'); +var Code = require('code'); +var Joi = require('../lib'); +var Helper = require('./helper'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +describe('ref', function () { + + it('uses ref as a valid value', function (done) { + + var schema = Joi.object({ + a: Joi.ref('b'), + b: Joi.any() + }); + + schema.validate({ a: 5, b: 6 }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('child "a" fails because ["a" must be one of [ref:b]]'); + + Helper.validate(schema, [ + [{ a: 5 }, false], + [{ b: 5 }, true], + [{ a: 5, b: 5 }, true], + [{ a: '5', b: '5' }, true] + ], done); + }); + }); + + it('uses ref as a valid value (empty key)', function (done) { + + var schema = Joi.object({ + a: Joi.ref(''), + '': Joi.any() + }); + + schema.validate({ a: 5, '': 6 }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('child "a" fails because ["a" must be one of [ref:]]'); + + Helper.validate(schema, [ + [{ a: 5 }, false], + [{ '': 5 }, true], + [{ a: 5, '': 5 }, true], + [{ a: '5', '': '5' }, true] + ], done); + }); + }); + + it('uses ref with nested keys as a valid value', function (done) { + + var schema = Joi.object({ + a: Joi.ref('b.c'), + b: { + c: Joi.any() + } + }); + + schema.validate({ a: 5, b: { c: 6 } }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('child "a" fails because ["a" must be one of [ref:b.c]]'); + + Helper.validate(schema, [ + [{ a: 5 }, false], + [{ b: { c: 5 } }, true], + [{ a: 5, b: 5 }, false], + [{ a: '5', b: { c: '5' } }, true] + ], done); + }); + }); + + it('uses ref with combined nested keys in sub child', function (done) { + + var ref = Joi.ref('b.c'); + expect(ref.root).to.equal('b'); + + var schema = Joi.object({ + a: ref, + b: { + c: Joi.any() + } + }); + + var input = { a: 5, b: { c: 5 } }; + schema.validate(input, function (err, value) { + + expect(err).to.not.exist(); + + var parent = Joi.object({ + e: schema + }); + + parent.validate({ e: input }, function (err2, value2) { + + expect(err2).to.not.exist(); + done(); + }); + }); + }); + + it('uses ref reach options', function (done) { + + var ref = Joi.ref('b/c', { separator: '/' }); + expect(ref.root).to.equal('b'); + + var schema = Joi.object({ + a: ref, + b: { + c: Joi.any() + } + }); + + schema.validate({ a: 5, b: { c: 5 } }, function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('ignores the order in which keys are defined', function (done) { + + var ab = Joi.object({ + a: { + c: Joi.number() + }, + b: Joi.ref('a.c') + }); + + ab.validate({ a: { c: '5' }, b: 5 }, function (err, value) { + + expect(err).to.not.exist(); + + var ba = Joi.object({ + b: Joi.ref('a.c'), + a: { + c: Joi.number() + } + }); + + ba.validate({ a: { c: '5' }, b: 5 }, function (err2, value2) { + + expect(err2).to.not.exist(); + done(); + }); + }); + }); + + it('uses ref as default value', function (done) { + + var schema = Joi.object({ + a: Joi.default(Joi.ref('b')), + b: Joi.any() + }); + + schema.validate({ b: 6 }, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal({ a: 6, b: 6 }); + done(); + }); + }); + + it('uses ref as default value regardless of order', function (done) { + + var ab = Joi.object({ + a: Joi.default(Joi.ref('b')), + b: Joi.number() + }); + + ab.validate({ b: '6' }, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal({ a: 6, b: 6 }); + + var ba = Joi.object({ + b: Joi.number(), + a: Joi.default(Joi.ref('b')) + }); + + ba.validate({ b: '6' }, function (err2, value2) { + + expect(err2).to.not.exist(); + expect(value2).to.deep.equal({ a: 6, b: 6 }); + done(); + }); + }); + }); + + it('ignores the order in which keys are defined with alternatives', function (done) { + + var a = { c: Joi.number() }; + var b = [Joi.ref('a.c'), Joi.ref('c')]; + var c = Joi.number(); + + Helper.validate({ a: a, b: b, c: c }, [ + [{ a: {} }, true], + [{ a: { c: '5' }, b: 5 }, true], + [{ a: { c: '5' }, b: 6, c: '6' }, true], + [{ a: { c: '5' }, b: 7, c: '6' }, false] + ]); + + Helper.validate({ b: b, a: a, c: c }, [ + [{ a: {} }, true], + [{ a: { c: '5' }, b: 5 }, true], + [{ a: { c: '5' }, b: 6, c: '6' }, true], + [{ a: { c: '5' }, b: 7, c: '6' }, false] + ]); + + Helper.validate({ b: b, c: c, a: a }, [ + [{ a: {} }, true], + [{ a: { c: '5' }, b: 5 }, true], + [{ a: { c: '5' }, b: 6, c: '6' }, true], + [{ a: { c: '5' }, b: 7, c: '6' }, false] + ]); + + Helper.validate({ a: a, c: c, b: b }, [ + [{ a: {} }, true], + [{ a: { c: '5' }, b: 5 }, true], + [{ a: { c: '5' }, b: 6, c: '6' }, true], + [{ a: { c: '5' }, b: 7, c: '6' }, false] + ]); + + Helper.validate({ c: c, a: a, b: b }, [ + [{ a: {} }, true], + [{ a: { c: '5' }, b: 5 }, true], + [{ a: { c: '5' }, b: 6, c: '6' }, true], + [{ a: { c: '5' }, b: 7, c: '6' }, false] + ]); + + Helper.validate({ c: c, b: b, a: a }, [ + [{ a: {} }, true], + [{ a: { c: '5' }, b: 5 }, true], + [{ a: { c: '5' }, b: 6, c: '6' }, true], + [{ a: { c: '5' }, b: 7, c: '6' }, false] + ], done); + }); + + it('uses context as default value', function (done) { + + var schema = Joi.object({ + a: Joi.default(Joi.ref('$x')), + b: Joi.any() + }); + + Joi.validate({ b: 6 }, schema, { context: { x: 22 } }, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal({ a: 22, b: 6 }); + done(); + }); + }); + + it('uses context as default value with custom prefix', function (done) { + + var schema = Joi.object({ + a: Joi.default(Joi.ref('%x', { contextPrefix: '%' })), + b: Joi.any() + }); + + Joi.validate({ b: 6 }, schema, { context: { x: 22 } }, function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.deep.equal({ a: 22, b: 6 }); + done(); + }); + }); + + it('uses context as a valid value', function (done) { + + var schema = Joi.object({ + a: Joi.ref('$x'), + b: Joi.any() + }); + + Joi.validate({ a: 5, b: 6 }, schema, { context: { x: 22 } }, function (err, value) { + + expect(err).to.exist(); + expect(err.message).to.equal('child "a" fails because ["a" must be one of [context:x]]'); + + Helper.validateOptions(schema, [ + [{ a: 5 }, false], + [{ a: 22 }, true], + [{ b: 5 }, true], + [{ a: 22, b: 5 }, true], + [{ a: '22', b: '5' }, false] + ], { context: { x: 22 } }, done); + }); + }); + + it('uses context in when condition', function (done) { + + var schema = { + a: Joi.boolean().when('$x', { is: Joi.exist(), otherwise: Joi.forbidden() }) + }; + + Helper.validate(schema, [ + [{}, true], + [{ a: 'x' }, false], + [{ a: true }, false], + [{}, true, { context: {} }], + [{ a: 'x' }, false, { context: {} }], + [{ a: true }, false, { context: {} }], + [{}, true, { context: { x: 1 } }], + [{ a: 'x' }, false, { context: { x: 1 } }], + [{ a: true }, true, { context: { x: 1 } }] + ], done); + }); + + it('uses nested context in when condition', function (done) { + + var schema = { + a: Joi.boolean().when('$x.y', { is: Joi.exist(), otherwise: Joi.forbidden() }) + }; + + Helper.validate(schema, [ + [{}, true], + [{ a: 'x' }, false], + [{ a: true }, false], + [{}, true, { context: {} }], + [{ a: 'x' }, false, { context: {} }], + [{ a: true }, false, { context: {} }], + [{}, true, { context: { x: 1 } }], + [{ a: 'x' }, false, { context: { x: 1 } }], + [{ a: true }, false, { context: { x: 1 } }], + [{}, true, { context: { x: {} } }], + [{ a: 'x' }, false, { context: { x: {} } }], + [{ a: true }, false, { context: { x: {} } }], + [{}, true, { context: { x: { y: 1 } } }], + [{ a: 'x' }, false, { context: { x: { y: 1 } } }], + [{ a: true }, true, { context: { x: { y: 1 } } }] + ], done); + }); + + it('describes schema with ref', function (done) { + + var desc = Joi.compile(Joi.ref('a.b')).describe(); + expect(Joi.isRef(desc.valids[0])).to.be.true(); + done(); + }); + + describe('#create', function () { + + it('throws when key is missing', function (done) { + + expect(function () { + + Joi.ref(5); + }).to.throw('Invalid reference key: 5'); + done(); + }); + + it('finds root with default separator', function (done) { + + expect(Joi.ref('a.b.c').root).to.equal('a'); + done(); + }); + + it('finds root with default separator and options', function (done) { + + expect(Joi.ref('a.b.c', {}).root).to.equal('a'); + done(); + }); + + it('finds root with custom separator', function (done) { + + expect(Joi.ref('a+b+c', { separator: '+' }).root).to.equal('a'); + done(); + }); + }); +});
@@ -0,0 +1,3035 @@
+// Load modules + +var Lab = require('lab'); +var Code = require('code'); +var Joi = require('../lib'); +var Helper = require('./helper'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var describe = lab.describe; +var it = lab.it; +var expect = Code.expect; + + +describe('string', function () { + + it('fails on boolean', function (done) { + + var schema = Joi.string(); + Helper.validate(schema, [ + [true, false], + [false, false] + ], done); + }); + + describe('#valid', function () { + + it('should throw error on input not matching type', function (done) { + + expect(function () { + + Joi.string().valid({}); + }).to.throw(); + done(); + }); + + it('should not throw on input matching type', function (done) { + + expect(function () { + + Joi.string().valid('joi'); + }).to.not.throw(); + done(); + }); + + it('validates case sensitive values', function (done) { + + Helper.validate(Joi.string().valid('a', 'b'), [ + ['a', true], + ['b', true], + ['A', false], + ['B', false] + ], done); + }); + + it('validates case insensitive values', function (done) { + + Helper.validate(Joi.string().valid('a', 'b').insensitive(), [ + ['a', true], + ['b', true], + ['A', true], + ['B', true], + [4, false] + ], done); + }); + + it('validates case insensitive values with non-strings', function (done) { + + Helper.validate(Joi.string().valid('a', 'b', 5).insensitive(), [ + ['a', true], + ['b', true], + ['A', true], + ['B', true], + [4, false], + [5, true] + ], done); + }); + }); + + describe('#invalid', function () { + + it('should throw error on input not matching type', function (done) { + + expect(function () { + + Joi.string().invalid({}); + }).to.throw(); + done(); + }); + + it('should not throw on input matching type', function (done) { + + expect(function () { + + Joi.string().invalid('joi'); + }).to.not.throw(); + done(); + }); + + it('invalidates case sensitive values', function (done) { + + Helper.validate(Joi.string().invalid('a', 'b'), [ + ['a', false], + ['b', false], + ['A', true], + ['B', true] + ], done); + }); + + it('invalidates case insensitive values', function (done) { + + Helper.validate(Joi.string().invalid('a', 'b').insensitive(), [ + ['a', false], + ['b', false], + ['A', false], + ['B', false] + ], done); + }); + }); + + describe('#min', function () { + + it('throws when limit is not a number', function (done) { + + expect(function () { + + Joi.string().min('a'); + }).to.throw('limit must be a positive integer or reference'); + done(); + }); + + it('throws when limit is not an integer', function (done) { + + expect(function () { + + Joi.string().min(1.2); + }).to.throw('limit must be a positive integer or reference'); + done(); + }); + + it('throws when limit is not a positive integer', function (done) { + + expect(function () { + + Joi.string().min(-1); + }).to.throw('limit must be a positive integer or reference'); + done(); + }); + + it('enforces a limit using byte count', function (done) { + + var schema = Joi.string().min(2, 'utf8'); + Helper.validate(schema, [ + ['\u00bd', true], + ['a', false] + ], done); + }); + + it('accepts references as min length', function (done) { + + var schema = Joi.object({ a: Joi.number(), b: Joi.string().min(Joi.ref('a'), 'utf8') }); + Helper.validate(schema, [ + [{ a: 2, b: '\u00bd' }, true], + [{ a: 2, b: 'a' }, false], + [{ a: 2, b: 'a' }, false, null, 'child "b" fails because ["b" length must be at least 2 characters long]'] + ], done); + }); + + it('accepts context references as min length', function (done) { + + var schema = Joi.object({ b: Joi.string().min(Joi.ref('$a'), 'utf8') }); + Helper.validate(schema, [ + [{ b: '\u00bd' }, true, { context: { a: 2 } }], + [{ b: 'a' }, false, { context: { a: 2 } }], + [{ b: 'a' }, false, { context: { a: 2 } }, 'child "b" fails because ["b" length must be at least 2 characters long]'] + ], done); + }); + + it('errors if reference is not a number', function (done) { + + var schema = Joi.object({ a: Joi.any(), b: Joi.string().min(Joi.ref('a'), 'utf8') }); + + Helper.validate(schema, [ + [{ a: 'Hi there', b: '\u00bd' }, false, null, 'child "b" fails because ["b" references "a" which is not a number]'] + ], done); + }); + + it('errors if context reference is not a number', function (done) { + + var schema = Joi.object({ b: Joi.string().min(Joi.ref('$a'), 'utf8') }); + + Helper.validate(schema, [ + [{ b: '\u00bd' }, false, { context: { a: 'Hi there' } }, 'child "b" fails because ["b" references "a" which is not a number]'] + ], done); + }); + }); + + describe('#max', function () { + + it('throws when limit is not a number', function (done) { + + expect(function () { + + Joi.string().max('a'); + }).to.throw('limit must be a positive integer or reference'); + done(); + }); + + it('throws when limit is not an integer', function (done) { + + expect(function () { + + Joi.string().max(1.2); + }).to.throw('limit must be a positive integer or reference'); + done(); + }); + + it('throws when limit is not a positive integer', function (done) { + + expect(function () { + + Joi.string().max(-1); + }).to.throw('limit must be a positive integer or reference'); + done(); + }); + + it('enforces a limit using byte count', function (done) { + + var schema = Joi.string().max(1, 'utf8'); + Helper.validate(schema, [ + ['\u00bd', false], + ['a', true] + ], done); + }); + + it('accepts references as min length', function (done) { + + var schema = Joi.object({ a: Joi.number(), b: Joi.string().max(Joi.ref('a'), 'utf8') }); + Helper.validate(schema, [ + [{ a: 2, b: '\u00bd' }, true], + [{ a: 2, b: 'three' }, false], + [{ a: 2, b: 'three' }, false, null, 'child "b" fails because ["b" length must be less than or equal to 2 characters long]'] + ], done); + }); + + it('accepts context references as min length', function (done) { + + var schema = Joi.object({ b: Joi.string().max(Joi.ref('$a'), 'utf8') }); + Helper.validate(schema, [ + [{ b: '\u00bd' }, true, { context: { a: 2 } }], + [{ b: 'three' }, false, { context: { a: 2 } }], + [{ b: 'three' }, false, { context: { a: 2 } }, 'child "b" fails because ["b" length must be less than or equal to 2 characters long]'] + ], done); + }); + + it('errors if reference is not a number', function (done) { + + var schema = Joi.object({ a: Joi.any(), b: Joi.string().max(Joi.ref('a'), 'utf8') }); + + Helper.validate(schema, [ + [{ a: 'Hi there', b: '\u00bd' }, false, null, 'child "b" fails because ["b" references "a" which is not a number]'] + ], done); + }); + + it('errors if context reference is not a number', function (done) { + + var schema = Joi.object({ b: Joi.string().max(Joi.ref('$a'), 'utf8') }); + + Helper.validate(schema, [ + [{ b: '\u00bd' }, false, { context: { a: 'Hi there' } }, 'child "b" fails because ["b" references "a" which is not a number]'] + ], done); + }); + }); + + describe('#creditCard', function () { + + it('should validate credit card', function (done) { + + var t = Joi.string().creditCard(); + t.validate('4111111111111112', function (err, value) { + + expect(err.message).to.equal('"value" must be a credit card'); + + Helper.validate(t, [ + ['378734493671000', true], // american express + ['371449635398431', true], // american express + ['378282246310005', true], // american express + ['341111111111111', true], // american express + ['5610591081018250', true], // australian bank + ['5019717010103742', true], // dankort pbs + ['38520000023237', true], // diners club + ['30569309025904', true], // diners club + ['6011000990139424', true], // discover + ['6011111111111117', true], // discover + ['6011601160116611', true], // discover + ['3566002020360505', true], // jbc + ['3530111333300000', true], // jbc + ['5105105105105100', true], // mastercard + ['5555555555554444', true], // mastercard + ['5431111111111111', true], // mastercard + ['6331101999990016', true], // switch/solo paymentech + ['4222222222222', true], // visa + ['4012888888881881', true], // visa + ['4111111111111111', true], // visa + ['4111111111111112', false], + [null, false] + ], done); + }); + }); + }); + + describe('#length', function () { + + it('throws when limit is not a number', function (done) { + + expect(function () { + + Joi.string().length('a'); + }).to.throw('limit must be a positive integer or reference'); + done(); + }); + + it('throws when limit is not an integer', function (done) { + + expect(function () { + + Joi.string().length(1.2); + }).to.throw('limit must be a positive integer or reference'); + done(); + }); + + it('throws when limit is not a positive integer', function (done) { + + expect(function () { + + Joi.string().length(-42); + }).to.throw('limit must be a positive integer or reference'); + done(); + }); + + it('enforces a limit using byte count', function (done) { + + var schema = Joi.string().length(2, 'utf8'); + Helper.validate(schema, [ + ['\u00bd', true], + ['a', false] + ], done); + }); + + it('accepts references as length', function (done) { + + var schema = Joi.object({ a: Joi.number(), b: Joi.string().length(Joi.ref('a'), 'utf8') }); + Helper.validate(schema, [ + [{ a: 2, b: '\u00bd' }, true], + [{ a: 2, b: 'a' }, false], + [{ a: 2, b: 'a' }, false, null, 'child "b" fails because ["b" length must be 2 characters long]'] + ], done); + }); + + it('accepts context references as length', function (done) { + + var schema = Joi.object({ b: Joi.string().length(Joi.ref('$a'), 'utf8') }); + Helper.validate(schema, [ + [{ b: '\u00bd' }, true, { context: { a: 2 } }], + [{ b: 'a' }, false, { context: { a: 2 } }], + [{ b: 'a' }, false, { context: { a: 2 } }, 'child "b" fails because ["b" length must be 2 characters long]'] + ], done); + }); + + it('errors if reference is not a number', function (done) { + + var schema = Joi.object({ a: Joi.any(), b: Joi.string().length(Joi.ref('a'), 'utf8') }); + + Helper.validate(schema, [ + [{ a: 'Hi there', b: '\u00bd' }, false, null, 'child "b" fails because ["b" references "a" which is not a number]'] + ], done); + }); + + it('errors if context reference is not a number', function (done) { + + var schema = Joi.object({ a: Joi.any(), b: Joi.string().length(Joi.ref('$a'), 'utf8') }); + + Helper.validate(schema, [ + [{ b: '\u00bd' }, false, { context: { a: 'Hi there' } }, 'child "b" fails because ["b" references "a" which is not a number]'] + ], done); + }); + }); + + describe('#email', function () { + + it('throws when options are not an object', function (done) { + + expect(function () { + + var emailOptions = true; + Joi.string().email(emailOptions); + }).to.throw('email options must be an object'); + done(); + }); + + it('throws when checkDNS option is enabled', function (done) { + + expect(function () { + + var emailOptions = { checkDNS: true }; + Joi.string().email(emailOptions); + }).to.throw('checkDNS option is not supported'); + done(); + }); + + it('throws when tldWhitelist is not an array or object', function (done) { + + expect(function () { + + var emailOptions = { tldWhitelist: 'domain.tld' }; + Joi.string().email(emailOptions); + }).to.throw('tldWhitelist must be an array or object'); + done(); + }); + + it('throws when minDomainAtoms is not a number', function (done) { + + expect(function () { + + var emailOptions = { minDomainAtoms: '1' }; + Joi.string().email(emailOptions); + }).to.throw('minDomainAtoms must be a positive integer'); + done(); + }); + + it('throws when minDomainAtoms is not an integer', function (done) { + + expect(function () { + + var emailOptions = { minDomainAtoms: 1.2 }; + Joi.string().email(emailOptions); + }).to.throw('minDomainAtoms must be a positive integer'); + done(); + }); + + it('throws when minDomainAtoms is not positive', function (done) { + + expect(function () { + + var emailOptions = { minDomainAtoms: 0 }; + Joi.string().email(emailOptions); + }).to.throw('minDomainAtoms must be a positive integer'); + done(); + }); + + it('does not throw when minDomainAtoms is a positive integer', function (done) { + + expect(function () { + + var emailOptions = { minDomainAtoms: 1 }; + Joi.string().email(emailOptions); + }).to.not.throw(); + done(); + }); + + it('throws when errorLevel is not an integer or boolean', function (done) { + + expect(function () { + + var emailOptions = { errorLevel: 1.2 }; + Joi.string().email(emailOptions); + }).to.throw('errorLevel must be a non-negative integer or boolean'); + done(); + }); + + it('throws when errorLevel is negative', function (done) { + + expect(function () { + + var emailOptions = { errorLevel: -1 }; + Joi.string().email(emailOptions); + }).to.throw('errorLevel must be a non-negative integer or boolean'); + done(); + }); + + it('does not throw when errorLevel is 0', function (done) { + + expect(function () { + + var emailOptions = { errorLevel: 0 }; + Joi.string().email(emailOptions); + }).to.not.throw(); + done(); + }); + }); + + describe('#hostname', function () { + + it('validates hostnames', function (done) { + + var schema = Joi.string().hostname(); + Helper.validate(schema, [ + ['www.example.com', true], + ['domain.local', true], + ['3domain.local', true], + ['hostname', true], + ['host:name', false], + ['-', false], + ['2387628', true], + ['01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789', false], + ['::1', true], + ['0:0:0:0:0:0:0:1', true], + ['0:?:0:0:0:0:0:1', false] + ], done); + }); + }); + + describe('#lowercase', function () { + + it('only allows strings that are entirely lowercase', function (done) { + + var schema = Joi.string().lowercase(); + Helper.validateOptions(schema, [ + ['this is all lowercase', true], + ['5', true], + ['lower\tcase', true], + ['Uppercase', false], + ['MixEd cAsE', false], + [1, false] + ], { convert: false }, done); + }); + + it('coerce string to lowercase before validation', function (done) { + + var schema = Joi.string().lowercase(); + schema.validate('UPPER TO LOWER', function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.equal('upper to lower'); + done(); + }); + }); + + it('should work in combination with a trim', function (done) { + + var schema = Joi.string().lowercase().trim(); + Helper.validate(schema, [ + [' abc', true], + [' ABC', true], + ['ABC', true], + [1, false] + ], done); + }); + + it('should work in combination with a replacement', function (done) { + + var schema = Joi.string().lowercase().replace(/\s+/g, ' '); + Helper.validate(schema, [ + ['a\r b\n c', true, null, 'a b c'], + ['A\t B C', true, null, 'a b c'], + ['ABC', true, null, 'abc'], + [1, false] + ], done); + }); + }); + + describe('#uppercase', function () { + + it('only allow strings that are entirely uppercase', function (done) { + + var schema = Joi.string().uppercase(); + Helper.validateOptions(schema, [ + ['THIS IS ALL UPPERCASE', true], + ['5', true], + ['UPPER\nCASE', true], + ['lOWERCASE', false], + ['MixEd cAsE', false], + [1, false] + ], { convert: false }, done); + }); + + it('coerce string to uppercase before validation', function (done) { + + var schema = Joi.string().uppercase(); + schema.validate('lower to upper', function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.equal('LOWER TO UPPER'); + done(); + }); + }); + + it('works in combination with a forced trim', function (done) { + + var schema = Joi.string().uppercase().trim(); + Helper.validate(schema, [ + [' abc', true], + [' ABC', true], + ['ABC', true], + [1, false] + ], done); + }); + + it('works in combination with a forced replacement', function (done) { + + var schema = Joi.string().uppercase().replace(/\s+/g, ' '); + Helper.validate(schema, [ + ['a\r b\n c', true, null, 'A B C'], + ['A\t B C', true, null, 'A B C'], + ['ABC', true, null, 'ABC'], + [1, false] + ], done); + }); + }); + + describe('#trim', function () { + + it('only allow strings that have no leading or trailing whitespace', function (done) { + + var schema = Joi.string().trim(); + Helper.validateOptions(schema, [ + [' something', false], + ['something ', false], + ['something\n', false], + ['some thing', true], + ['something', true] + ], { convert: false }, done); + }); + + it('removes leading and trailing whitespace before validation', function (done) { + + var schema = Joi.string().trim(); + schema.validate(' trim this ', function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.equal('trim this'); + done(); + }); + }); + + it('removes leading and trailing whitespace before validation', function (done) { + + var schema = Joi.string().trim().allow(''); + schema.validate(' ', function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.equal(''); + done(); + }); + }); + + it('should work in combination with min', function (done) { + + var schema = Joi.string().min(4).trim(); + Helper.validate(schema, [ + [' a ', false], + ['abc ', false], + ['abcd ', true] + ], done); + }); + + it('should work in combination with max', function (done) { + + var schema = Joi.string().max(4).trim(); + Helper.validate(schema, [ + [' abcde ', false], + ['abc ', true], + ['abcd ', true] + ], done); + }); + + it('should work in combination with length', function (done) { + + var schema = Joi.string().length(4).trim(); + Helper.validate(schema, [ + [' ab ', false], + ['abc ', false], + ['abcd ', true] + ], done); + }); + + it('should work in combination with a case change', function (done) { + + var schema = Joi.string().trim().lowercase(); + Helper.validate(schema, [ + [' abc', true], + [' ABC', true], + ['ABC', true] + ], done); + }); + }); + + describe('#replace', function () { + + it('successfully replaces the first occurrence of the expression', function (done) { + + var schema = Joi.string().replace(/\s+/, ''); // no "g" flag + Helper.validateOptions(schema, [ + ['\tsomething', true, null, 'something'], + ['something\r', true, null, 'something'], + ['something ', true, null, 'something'], + ['some thing', true, null, 'something'], + ['so me thing', true, null, 'some thing'] // first occurrence! + ], { convert: true }, done); + }); + + it('successfully replaces all occurrences of the expression', function (done) { + + var schema = Joi.string().replace(/\s+/g, ''); // has "g" flag + Helper.validateOptions(schema, [ + ['\tsomething', true, null, 'something'], + ['something\r', true, null, 'something'], + ['something ', true, null, 'something'], + ['some thing', true, null, 'something'], + ['so me thing', true, null, 'something'] + ], { convert: true }, done); + }); + + it('successfully replaces all occurrences of a string pattern', function (done) { + + var schema = Joi.string().replace('foo', 'X'); // has "g" flag + Helper.validateOptions(schema, [ + ['foobarfoobazfoo', true, null, 'XbarXbazX'] + ], { convert: true }, done); + }); + + it('successfully replaces multiple times', function (done) { + + var schema = Joi.string().replace(/a/g, 'b').replace(/b/g, 'c'); + schema.validate('a quick brown fox', function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.equal('c quick crown fox'); + done(); + }); + }); + + it('should work in combination with trim', function (done) { + + // The string below is the name "Yamada Tarou" separated by a + // carriage return, a "full width" ideographic space and a newline + + var schema = Joi.string().trim().replace(/\s+/g, ' '); + schema.validate(' \u5C71\u7530\r\u3000\n\u592A\u90CE ', function (err, value) { + + expect(err).to.not.exist(); + expect(value).to.equal('\u5C71\u7530 \u592A\u90CE'); + done(); + }); + }); + + it('should work in combination with min', function (done) { + + var schema = Joi.string().min(4).replace(/\s+/g, ' '); + Helper.validate(schema, [ + [' a ', false], + ['abc ', true, null, 'abc '], + ['a\t\rbc', true, null, 'a bc'] + ], done); + }); + + it('should work in combination with max', function (done) { + + var schema = Joi.string().max(5).replace(/ CHANGE ME /g, '-b-'); + Helper.validate(schema, [ + ['a CHANGE ME c', true, null, 'a-b-c'], + ['a-b-c', true, null, 'a-b-c'] // nothing changes here! + ], done); + }); + + it('should work in combination with length', function (done) { + + var schema = Joi.string().length(5).replace(/\s+/g, ' '); + Helper.validate(schema, [ + ['a bc', false], + ['a\tb\nc', true, null, 'a b c'] + ], done); + }); + + }); + + describe('#regex', function () { + + it('should not include a pattern name by default', function (done) { + + var schema = Joi.string().regex(/[a-z]+/).regex(/[0-9]+/); + schema.validate('abcd', function (err, value) { + + expect(err.message).to.contain('required pattern'); + done(); + }); + }); + + it('should include a pattern name if specified', function (done) { + + var schema = Joi.string().regex(/[a-z]+/, 'letters').regex(/[0-9]+/, 'numbers'); + schema.validate('abcd', function (err, value) { + + expect(err.message).to.contain('numbers pattern'); + done(); + }); + }); + }); + + describe('#ip', function () { + + var invalidIPs = [ + ['ASDF', false], + ['192.0.2.16:80/30', false], + ['192.0.2.16a', false], + ['qwerty', false], + ['127.0.0.1:8000', false], + ['ftp://www.example.com', false], + ['Bananas in pajamas are coming down the stairs', false] + ], + invalidIPv4s = [ + ['0.0.0.0/33', false], + ['256.0.0.0/0', false], + ['255.255.255.256/32', false], + ['256.0.0.0', false], + ['255.255.255.256', false] + ], + invalidIPv6s = [ + ['2001:db8::7/33', false], + ['1080:0:0:0:8:800:200C:417G', false] + ], + invalidIPvFutures = [ + ['v1.09azAZ-._~!$&\'()*+,;=:/33', false], + ['v1.09#', false] + ], + validIPv4sWithCidr = function (success) { + + return [ + ['0.0.0.0/32', success], + ['255.255.255.255/0', success], + ['127.0.0.1/0', success], + ['192.168.2.1/0', success], + ['0.0.0.3/2', success], + ['0.0.0.7/3', success], + ['0.0.0.15/4', success], + ['0.0.0.31/5', success], + ['0.0.0.63/6', success], + ['0.0.0.127/7', success], + ['01.020.030.100/7', success], + ['0.0.0.0/0', success], + ['00.00.00.00/0', success], + ['000.000.000.000/32', success] + ]; + }, + validIPv4sWithoutCidr = function (success) { + + return [ + ['0.0.0.0', success], + ['255.255.255.255', success], + ['127.0.0.1', success], + ['192.168.2.1', success], + ['0.0.0.3', success], + ['0.0.0.7', success], + ['0.0.0.15', success], + ['0.0.0.31', success], + ['0.0.0.63', success], + ['0.0.0.127', success], + ['01.020.030.100', success], + ['0.0.0.0', success], + ['00.00.00.00', success], + ['000.000.000.000', success] + ]; + }, + validIPv6sWithCidr = function (success) { + + return [ + ['2001:db8::7/32', success], + ['a:b:c:d:e::1.2.3.4/13', success], + ['FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/0', success], + ['FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/32', success], + ['1080:0:0:0:8:800:200C:417A/27', success] + ]; + }, + validIPv6sWithoutCidr = function (success) { + + return [ + ['2001:db8::7', success], + ['a:b:c:d:e::1.2.3.4', success], + ['FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', success], + ['FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', success], + ['1080:0:0:0:8:800:200C:417A', success] + ]; + }, + validIPvFuturesWithCidr = function (success) { + + return [ + ['v1.09azAZ-._~!$&\'()*+,;=:/32', success] + ]; + }, + validIPvFuturesWithoutCidr = function (success) { + + return [ + ['v1.09azAZ-._~!$&\'()*+,;=:', success] + ]; + }; + + it('should validate all ip addresses with optional CIDR by default', function (done) { + + var schema = Joi.string().ip(); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(true)) + .concat(validIPv4sWithoutCidr(true)) + .concat(validIPv6sWithCidr(true)) + .concat(validIPv6sWithoutCidr(true)) + .concat(validIPvFuturesWithCidr(true)) + .concat(validIPvFuturesWithoutCidr(true)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ip addresses with an optional CIDR', function (done) { + + var schema = Joi.string().ip({ cidr: 'optional' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(true)) + .concat(validIPv4sWithoutCidr(true)) + .concat(validIPv6sWithCidr(true)) + .concat(validIPv6sWithoutCidr(true)) + .concat(validIPvFuturesWithCidr(true)) + .concat(validIPvFuturesWithoutCidr(true)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ip addresses with a required CIDR', function (done) { + + var schema = Joi.string().ip({ cidr: 'required' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(true)) + .concat(validIPv4sWithoutCidr(false)) + .concat(validIPv6sWithCidr(true)) + .concat(validIPv6sWithoutCidr(false)) + .concat(validIPvFuturesWithCidr(true)) + .concat(validIPvFuturesWithoutCidr(false)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ip addresses with a forbidden CIDR', function (done) { + + var schema = Joi.string().ip({ cidr: 'forbidden' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(false)) + .concat(validIPv4sWithoutCidr(true)) + .concat(validIPv6sWithCidr(false)) + .concat(validIPv6sWithoutCidr(true)) + .concat(validIPvFuturesWithCidr(false)) + .concat(validIPvFuturesWithoutCidr(true)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('throws when options is not an object', function (done) { + + expect(function () { + + Joi.string().ip(42); + }).to.throw('options must be an object'); + done(); + }); + + it('throws when options.cidr is not a string', function (done) { + + expect(function () { + + Joi.string().ip({ cidr: 42 }); + }).to.throw('cidr must be a string'); + done(); + }); + + it('throws when options.cidr is not a valid value', function (done) { + + expect(function () { + + Joi.string().ip({ cidr: '42' }); + }).to.throw('cidr must be one of required, optional, forbidden'); + done(); + }); + + it('throws when options.version is an empty array', function (done) { + + expect(function () { + + Joi.string().ip({ version: [] }); + }).to.throw('version must have at least 1 version specified'); + done(); + }); + + it('throws when options.version is not a string', function (done) { + + expect(function () { + + Joi.string().ip({ version: 42 }); + }).to.throw('version at position 0 must be a string'); + done(); + }); + + it('throws when options.version is not a valid value', function (done) { + + expect(function () { + + Joi.string().ip({ version: '42' }); + }).to.throw('version at position 0 must be one of ipv4, ipv6, ipvfuture'); + done(); + }); + + it('validates ip with a friendly error message', function (done) { + + var schema = { item: Joi.string().ip() }; + Joi.compile(schema).validate({ item: 'something' }, function (err, value) { + + expect(err.message).to.contain('must be a valid ip address'); + done(); + }); + }); + + it('validates ip and cidr presence with a friendly error message', function (done) { + + var schema = { item: Joi.string().ip({ cidr: 'required' }) }; + Joi.compile(schema).validate({ item: 'something' }, function (err, value) { + + expect(err.message).to.contain('must be a valid ip address with a required CIDR'); + done(); + }); + }); + + it('validates custom ip version and cidr presence with a friendly error message', function (done) { + + var schema = { item: Joi.string().ip({ version: 'ipv4', cidr: 'required' }) }; + Joi.compile(schema).validate({ item: 'something' }, function (err, value) { + + expect(err.message).to.contain('child "item" fails because ["item" must be a valid ip address of one of the following versions [ipv4] with a required CIDR]'); + done(); + }); + }); + + describe('#ip({ version: "ipv4" })', function () { + + it('should validate all ipv4 addresses with a default CIDR strategy', function (done) { + + var schema = Joi.string().ip({ version: 'ipv4' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(true)) + .concat(validIPv4sWithoutCidr(true)) + .concat(validIPv6sWithCidr(false)) + .concat(validIPv6sWithoutCidr(false)) + .concat(validIPvFuturesWithCidr(false)) + .concat(validIPvFuturesWithoutCidr(false)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ipv4 addresses with an optional CIDR', function (done) { + + var schema = Joi.string().ip({ version: 'ipv4', cidr: 'optional' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(true)) + .concat(validIPv4sWithoutCidr(true)) + .concat(validIPv6sWithCidr(false)) + .concat(validIPv6sWithoutCidr(false)) + .concat(validIPvFuturesWithCidr(false)) + .concat(validIPvFuturesWithoutCidr(false)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ipv4 addresses with a required CIDR', function (done) { + + var schema = Joi.string().ip({ version: 'ipv4', cidr: 'required' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(true)) + .concat(validIPv4sWithoutCidr(false)) + .concat(validIPv6sWithCidr(false)) + .concat(validIPv6sWithoutCidr(false)) + .concat(validIPvFuturesWithCidr(false)) + .concat(validIPvFuturesWithoutCidr(false)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ipv4 addresses with a forbidden CIDR', function (done) { + + var schema = Joi.string().ip({ version: 'ipv4', cidr: 'forbidden' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(false)) + .concat(validIPv4sWithoutCidr(true)) + .concat(validIPv6sWithCidr(false)) + .concat(validIPv6sWithoutCidr(false)) + .concat(validIPvFuturesWithCidr(false)) + .concat(validIPvFuturesWithoutCidr(false)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + }); + + describe('#ip({ version: "ipv6" })', function () { + + it('should validate all ipv6 addresses with a default CIDR strategy', function (done) { + + var schema = Joi.string().ip({ version: 'ipv6' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(false)) + .concat(validIPv4sWithoutCidr(false)) + .concat(validIPv6sWithCidr(true)) + .concat(validIPv6sWithoutCidr(true)) + .concat(validIPvFuturesWithCidr(false)) + .concat(validIPvFuturesWithoutCidr(false)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ipv6 addresses with an optional CIDR', function (done) { + + var schema = Joi.string().ip({ version: 'ipv6', cidr: 'optional' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(false)) + .concat(validIPv4sWithoutCidr(false)) + .concat(validIPv6sWithCidr(true)) + .concat(validIPv6sWithoutCidr(true)) + .concat(validIPvFuturesWithCidr(false)) + .concat(validIPvFuturesWithoutCidr(false)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ipv6 addresses with a required CIDR', function (done) { + + var schema = Joi.string().ip({ version: 'ipv6', cidr: 'required' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(false)) + .concat(validIPv4sWithoutCidr(false)) + .concat(validIPv6sWithCidr(true)) + .concat(validIPv6sWithoutCidr(false)) + .concat(validIPvFuturesWithCidr(false)) + .concat(validIPvFuturesWithoutCidr(false)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ipv6 addresses with a forbidden CIDR', function (done) { + + var schema = Joi.string().ip({ version: 'ipv6', cidr: 'forbidden' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(false)) + .concat(validIPv4sWithoutCidr(false)) + .concat(validIPv6sWithCidr(false)) + .concat(validIPv6sWithoutCidr(true)) + .concat(validIPvFuturesWithCidr(false)) + .concat(validIPvFuturesWithoutCidr(false)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + }); + + describe('#ip({ version: "ipvfuture" })', function () { + + it('should validate all ipvfuture addresses with a default CIDR strategy', function (done) { + + var schema = Joi.string().ip({ version: 'ipvfuture' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(false)) + .concat(validIPv4sWithoutCidr(false)) + .concat(validIPv6sWithCidr(false)) + .concat(validIPv6sWithoutCidr(false)) + .concat(validIPvFuturesWithCidr(true)) + .concat(validIPvFuturesWithoutCidr(true)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ipvfuture addresses with an optional CIDR', function (done) { + + var schema = Joi.string().ip({ version: 'ipvfuture', cidr: 'optional' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(false)) + .concat(validIPv4sWithoutCidr(false)) + .concat(validIPv6sWithCidr(false)) + .concat(validIPv6sWithoutCidr(false)) + .concat(validIPvFuturesWithCidr(true)) + .concat(validIPvFuturesWithoutCidr(true)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ipvfuture addresses with a required CIDR', function (done) { + + var schema = Joi.string().ip({ version: 'ipvfuture', cidr: 'required' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(false)) + .concat(validIPv4sWithoutCidr(false)) + .concat(validIPv6sWithCidr(false)) + .concat(validIPv6sWithoutCidr(false)) + .concat(validIPvFuturesWithCidr(true)) + .concat(validIPvFuturesWithoutCidr(false)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ipvfuture addresses with a forbidden CIDR', function (done) { + + var schema = Joi.string().ip({ version: 'ipvfuture', cidr: 'forbidden' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(false)) + .concat(validIPv4sWithoutCidr(false)) + .concat(validIPv6sWithCidr(false)) + .concat(validIPv6sWithoutCidr(false)) + .concat(validIPvFuturesWithCidr(false)) + .concat(validIPvFuturesWithoutCidr(true)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + }); + + describe('#ip({ version: [ "ipv4", "ipv6" ] })', function () { + + it('should validate all ipv4 and ipv6 addresses with a default CIDR strategy', function (done) { + + var schema = Joi.string().ip({ version: ['ipv4', 'ipv6'] }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(true)) + .concat(validIPv4sWithoutCidr(true)) + .concat(validIPv6sWithCidr(true)) + .concat(validIPv6sWithoutCidr(true)) + .concat(validIPvFuturesWithCidr(false)) + .concat(validIPvFuturesWithoutCidr(false)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ipv4 and ipv6 addresses with an optional CIDR', function (done) { + + var schema = Joi.string().ip({ version: ['ipv4', 'ipv6'], cidr: 'optional' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(true)) + .concat(validIPv4sWithoutCidr(true)) + .concat(validIPv6sWithCidr(true)) + .concat(validIPv6sWithoutCidr(true)) + .concat(validIPvFuturesWithCidr(false)) + .concat(validIPvFuturesWithoutCidr(false)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ipv4 and ipv6 addresses with a required CIDR', function (done) { + + var schema = Joi.string().ip({ version: ['ipv4', 'ipv6'], cidr: 'required' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(true)) + .concat(validIPv4sWithoutCidr(false)) + .concat(validIPv6sWithCidr(true)) + .concat(validIPv6sWithoutCidr(false)) + .concat(validIPvFuturesWithCidr(false)) + .concat(validIPvFuturesWithoutCidr(false)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + + it('should validate all ipv4 and ipv6 addresses with a forbidden CIDR', function (done) { + + var schema = Joi.string().ip({ version: ['ipv4', 'ipv6'], cidr: 'forbidden' }); + Helper.validate(schema, [] + .concat(validIPv4sWithCidr(false)) + .concat(validIPv4sWithoutCidr(true)) + .concat(validIPv6sWithCidr(false)) + .concat(validIPv6sWithoutCidr(true)) + .concat(validIPvFuturesWithCidr(false)) + .concat(validIPvFuturesWithoutCidr(false)) + .concat(invalidIPs) + .concat(invalidIPv4s) + .concat(invalidIPv6s) + .concat(invalidIPvFutures), done); + }); + }); + }); + + describe('#validate', function () { + + it('should, by default, allow undefined, deny empty string', function (done) { + + Helper.validate(Joi.string(), [ + [undefined, true], + ['', false] + ], done); + }); + + it('should, when .required(), deny undefined, deny empty string', function (done) { + + Helper.validate(Joi.string().required(), [ + [undefined, false], + ['', false] + ], done); + }); + + it('should, when .required(), print a friend error message for an empty string', function (done) { + + var schema = Joi.string().required(); + Joi.compile(schema).validate('', function (err, value) { + + expect(err.message).to.contain('be empty'); + done(); + }); + }); + + it('should, when .required(), validate non-empty strings', function (done) { + + var schema = Joi.string().required(); + Helper.validate(schema, [ + ['test', true], + ['0', true], + [null, false] + ], done); + }); + + it('validates invalid values', function (done) { + + var schema = Joi.string().invalid('a', 'b', 'c'); + Helper.validate(schema, [ + ['x', true], + ['a', false], + ['c', false] + ], done); + }); + + it('should invalidate invalid values', function (done) { + + var schema = Joi.string().valid('a', 'b', 'c'); + Helper.validate(schema, [ + ['x', false], + ['a', true], + ['c', true] + ], done); + }); + + it('validates array arguments correctly', function (done) { + + var schema = Joi.string().valid(['a', 'b', 'c']); + Helper.validate(schema, [ + ['x', false], + ['a', true], + ['c', true] + ], done); + }); + + it('validates minimum length when min is used', function (done) { + + var schema = Joi.string().min(3); + Helper.validate(schema, [ + ['test', true], + ['0', false], + [null, false] + ], done); + }); + + it('validates minimum length when min is 0', function (done) { + + var schema = Joi.string().min(0).required(); + Helper.validate(schema, [ + ['0', true], + [null, false], + [undefined, false] + ], done); + }); + + it('should return false with minimum length and a null value passed in', function (done) { + + var schema = Joi.string().min(3); + Helper.validate(schema, [ + [null, false] + ], done); + }); + + it('null allowed overrides min length requirement', function (done) { + + var schema = Joi.string().min(3).allow(null); + Helper.validate(schema, [ + [null, true] + ], done); + }); + + it('validates maximum length when max is used', function (done) { + + var schema = Joi.string().max(3); + Helper.validate(schema, [ + ['test', false], + ['0', true], + [null, false] + ], done); + }); + + it('should return true with max and not required when value is undefined', function (done) { + + var schema = Joi.string().max(3); + Helper.validate(schema, [ + [undefined, true] + ], done); + }); + + it('validates length requirements', function (done) { + + var schema = Joi.string().length(3); + Helper.validate(schema, [ + ['test', false], + ['0', false], + [null, false], + ['abc', true] + ], done); + }); + + it('validates regex', function (done) { + + var schema = Joi.string().regex(/^[0-9][-][a-z]+$/); + Helper.validate(schema, [ + ['van', false], + ['0-www', true] + ], done); + }); + + it('validates regex (ignoring global flag)', function (done) { + + var schema = Joi.string().regex(/a/g); + Helper.validate(schema, [ + ['ab', true], + ['ac', true] + ], done); + }); + + it('validates token', function (done) { + + var schema = Joi.string().token(); + Helper.validate(schema, [ + ['w0rld_of_w4lm4rtl4bs', true], + ['w0rld of_w4lm4rtl4bs', false], + ['abcd#f?h1j orly?', false] + ], done); + }); + + it('validates alphanum', function (done) { + + var schema = Joi.string().alphanum(); + Helper.validate(schema, [ + ['w0rld of w4lm4rtl4bs', false], + ['w0rldofw4lm4rtl4bs', true], + ['abcd#f?h1j orly?', false] + ], done); + }); + + it('validates email', function (done) { + + var schema = Joi.string().email(); + Helper.validate(schema, [ + ['joe@example.com', true], + ['"joe"@example.com', true], + ['@iaminvalid.com', false], + ['joe@[IPv6:2a00:1450:4001:c02::1b]', true], + ['12345678901234567890123456789012345678901234567890123456789012345@walmartlabs.com', false], + ['123456789012345678901234567890123456789012345678901234567890@12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.12345.toolong.com', false] + ], done); + }); + + it('validates email with tldWhitelist as array', function (done) { + + var schema = Joi.string().email({ tldWhitelist: ['com', 'org'] }); + Helper.validate(schema, [ + ['joe@example.com', true], + ['joe@example.org', true], + ['joe@example.edu', false] + ], done); + }); + + it('validates email with tldWhitelist as object', function (done) { + + var schema = Joi.string().email({ tldWhitelist: { com: true, org: true } }); + Helper.validate(schema, [ + ['joe@example.com', true], + ['joe@example.org', true], + ['joe@example.edu', false] + ], done); + }); + + it('validates email with minDomainAtoms', function (done) { + + var schema = Joi.string().email({ minDomainAtoms: 4 }); + Helper.validate(schema, [ + ['joe@example.com', false], + ['joe@www.example.com', false], + ['joe@sub.www.example.com', true] + ], done); + }); + + it('validates email with errorLevel as boolean', function (done) { + + var schema = Joi.string().email({ errorLevel: false }); + Helper.validate(schema, [ + ['joe@example.com', true], + ['joe@www.example.com', true], + ['joe@localhost', true], + ['joe', false] + ]); + + schema = Joi.string().email({ errorLevel: true }); + Helper.validate(schema, [ + ['joe@example.com', true], + ['joe@www.example.com', true], + ['joe@localhost', false], + ['joe', false] + ], done); + }); + + it('validates email with errorLevel as integer', function (done) { + + var schema = Joi.string().email({ errorLevel: 10 }); + Helper.validate(schema, [ + ['joe@example.com', true], + ['joe@www.example.com', true], + ['joe@localhost', true], + ['joe', false] + ], done); + }); + + it('validates email with a friendly error message', function (done) { + + var schema = { item: Joi.string().email() }; + Joi.compile(schema).validate({ item: 'something' }, function (err, value) { + + expect(err.message).to.contain('must be a valid email'); + done(); + }); + }); + + it('should return false for denied value', function (done) { + + var text = Joi.string().invalid('joi'); + text.validate('joi', function (err, value) { + + expect(err).to.exist(); + done(); + }); + }); + + it('should return true for allowed value', function (done) { + + var text = Joi.string().allow('hapi'); + text.validate('result', function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('validates with one validator (min)', function (done) { + + var text = Joi.string().min(3); + text.validate('joi', function (err, value) { + + expect(err).to.not.exist(); + done(); + }); + }); + + it('validates with two validators (min, required)', function (done) { + + var text = Joi.string().min(3).required(); + text.validate('joi', function (err, value) { + + expect(err).to.not.exist(); + + text.validate('', function (err2, value2) { + + expect(err2).to.exist(); + done(); + }); + }); + }); + + it('validates null with allow(null)', function (done) { + + Helper.validate(Joi.string().allow(null), [ + [null, true] + ], done); + }); + + it('validates "" (empty string) with allow(\'\')', function (done) { + + Helper.validate(Joi.string().allow(''), [ + ['', true], + ['', true] + ], done); + }); + + it('validates combination of required and min', function (done) { + + var rule = Joi.string().required().min(3); + Helper.validate(rule, [ + ['x', false], + ['123', true], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of required and max', function (done) { + + var rule = Joi.string().required().max(3); + Helper.validate(rule, [ + ['x', true], + ['123', true], + ['1234', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of allow(\'\') and min', function (done) { + + var rule = Joi.string().allow('').min(3); + Helper.validate(rule, [ + ['x', false], + ['123', true], + ['1234', true], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of allow(\'\') and max', function (done) { + + var rule = Joi.string().allow('').max(3); + Helper.validate(rule, [ + ['x', true], + ['123', true], + ['1234', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of null allowed and max', function (done) { + + var rule = Joi.string().allow(null).max(3); + Helper.validate(rule, [ + ['x', true], + ['123', true], + ['1234', false], + ['', false], + [null, true] + ], done); + }); + + it('validates combination of min and max', function (done) { + + var rule = Joi.string().min(2).max(3); + Helper.validate(rule, [ + ['x', false], + ['123', true], + ['1234', false], + ['12', true], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of min, max, and allow(\'\')', function (done) { + + var rule = Joi.string().min(2).max(3).allow(''); + Helper.validate(rule, [ + ['x', false], + ['123', true], + ['1234', false], + ['12', true], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of min, max, and required', function (done) { + + var rule = Joi.string().min(2).max(3).required(); + Helper.validate(rule, [ + ['x', false], + ['123', true], + ['1234', false], + ['12', true], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of min, max, and regex', function (done) { + + var rule = Joi.string().min(2).max(3).regex(/^a/); + Helper.validate(rule, [ + ['x', false], + ['123', false], + ['1234', false], + ['12', false], + ['ab', true], + ['abc', true], + ['abcd', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of min, max, regex, and allow(\'\')', function (done) { + + var rule = Joi.string().min(2).max(3).regex(/^a/).allow(''); + Helper.validate(rule, [ + ['x', false], + ['123', false], + ['1234', false], + ['12', false], + ['ab', true], + ['abc', true], + ['abcd', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of min, max, regex, and required', function (done) { + + var rule = Joi.string().min(2).max(3).regex(/^a/).required(); + Helper.validate(rule, [ + ['x', false], + ['123', false], + ['1234', false], + ['12', false], + ['ab', true], + ['abc', true], + ['abcd', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of min, max, and alphanum', function (done) { + + var rule = Joi.string().min(2).max(3).alphanum(); + Helper.validate(rule, [ + ['x', false], + ['123', true], + ['1234', false], + ['12', true], + ['ab', true], + ['abc', true], + ['abcd', false], + ['*ab', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of min, max, alphanum, and allow(\'\')', function (done) { + + var rule = Joi.string().min(2).max(3).alphanum().allow(''); + Helper.validate(rule, [ + ['x', false], + ['123', true], + ['1234', false], + ['12', true], + ['ab', true], + ['abc', true], + ['abcd', false], + ['*ab', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of min, max, alphanum, and required', function (done) { + + var rule = Joi.string().min(2).max(3).alphanum().required(); + Helper.validate(rule, [ + ['x', false], + ['123', true], + ['1234', false], + ['12', true], + ['ab', true], + ['abc', true], + ['abcd', false], + ['*ab', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of min, max, alphanum, and regex', function (done) { + + var rule = Joi.string().min(2).max(3).alphanum().regex(/^a/); + Helper.validate(rule, [ + ['x', false], + ['123', false], + ['1234', false], + ['12', false], + ['ab', true], + ['abc', true], + ['a2c', true], + ['abcd', false], + ['*ab', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of min, max, alphanum, required, and regex', function (done) { + + var rule = Joi.string().min(2).max(3).alphanum().required().regex(/^a/); + Helper.validate(rule, [ + ['x', false], + ['123', false], + ['1234', false], + ['12', false], + ['ab', true], + ['abc', true], + ['a2c', true], + ['abcd', false], + ['*ab', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of min, max, alphanum, allow(\'\'), and regex', function (done) { + + var rule = Joi.string().min(2).max(3).alphanum().allow('').regex(/^a/); + Helper.validate(rule, [ + ['x', false], + ['123', false], + ['1234', false], + ['12', false], + ['ab', true], + ['abc', true], + ['a2c', true], + ['abcd', false], + ['*ab', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of email and min', function (done) { + + var rule = Joi.string().email().min(8); + Helper.validate(rule, [ + ['x@x.com', false], + ['123@x.com', true], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of email, min, and max', function (done) { + + var rule = Joi.string().email().min(8).max(10); + Helper.validate(rule, [ + ['x@x.com', false], + ['123@x.com', true], + ['1234@x.com', true], + ['12345@x.com', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of email, min, max, and invalid', function (done) { + + var rule = Joi.string().email().min(8).max(10).invalid('123@x.com'); + Helper.validate(rule, [ + ['x@x.com', false], + ['123@x.com', false], + ['1234@x.com', true], + ['12345@x.com', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of email, min, max, and allow', function (done) { + + var rule = Joi.string().email().min(8).max(10).allow('x@x.com'); + Helper.validate(rule, [ + ['x@x.com', true], + ['123@x.com', true], + ['1234@x.com', true], + ['12345@x.com', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of email, min, max, allow, and invalid', function (done) { + + var rule = Joi.string().email().min(8).max(10).allow('x@x.com').invalid('123@x.com'); + Helper.validate(rule, [ + ['x@x.com', true], + ['123@x.com', false], + ['1234@x.com', true], + ['12345@x.com', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of email, min, max, allow, invalid, and allow(\'\')', function (done) { + + var rule = Joi.string().email().min(8).max(10).allow('x@x.com').invalid('123@x.com').allow(''); + Helper.validate(rule, [ + ['x@x.com', true], + ['123@x.com', false], + ['1234@x.com', true], + ['12345@x.com', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of email, min, max, allow, and allow(\'\')', function (done) { + + var rule = Joi.string().email().min(8).max(10).allow('x@x.com').allow(''); + Helper.validate(rule, [ + ['x@x.com', true], + ['123@x.com', true], + ['1234@x.com', true], + ['12345@x.com', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of email, min, max, allow, invalid, and regex', function (done) { + + var rule = Joi.string().email().min(8).max(10).allow('x@x.com').invalid('123@x.com').regex(/^1/); + Helper.validate(rule, [ + ['x@x.com', true], + ['123@x.com', false], + ['1234@x.com', true], + ['12345@x.com', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of email, min, max, allow, invalid, regex, and allow(\'\')', function (done) { + + var rule = Joi.string().email().min(8).max(10).allow('x@x.com').invalid('123@x.com').regex(/^1/).allow(''); + Helper.validate(rule, [ + ['x@x.com', true], + ['123@x.com', false], + ['1234@x.com', true], + ['12345@x.com', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of email, min, max, and allow(\'\')', function (done) { + + var rule = Joi.string().email().min(8).max(10).allow(''); + Helper.validate(rule, [ + ['x@x.com', false], + ['123@x.com', true], + ['1234@x.com', true], + ['12345@x.com', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of email, min, max, and regex', function (done) { + + var rule = Joi.string().email().min(8).max(10).regex(/^1234/); + Helper.validate(rule, [ + ['x@x.com', false], + ['123@x.com', false], + ['1234@x.com', true], + ['12345@x.com', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of email, min, max, regex, and allow(\'\')', function (done) { + + var rule = Joi.string().email().min(8).max(10).regex(/^1234/).allow(''); + Helper.validate(rule, [ + ['x@x.com', false], + ['123@x.com', false], + ['1234@x.com', true], + ['12345@x.com', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of email, min, max, regex, and required', function (done) { + + var rule = Joi.string().email().min(8).max(10).regex(/^1234/).required(); + Helper.validate(rule, [ + ['x@x.com', false], + ['123@x.com', false], + ['1234@x.com', true], + ['12345@x.com', false], + ['', false], + [null, false] + ], done); + }); + + it('validates uri', function (done) { + + // Handful of tests taken from Node: https://github.com/joyent/node/blob/cfcb1de130867197cbc9c6012b7e84e08e53d032/test/simple/test-url.js + // Also includes examples from RFC 8936: http://tools.ietf.org/html/rfc3986#page-7 + var schema = Joi.string().uri(); + + Helper.validate(schema, [ + ['foo://example.com:8042/over/there?name=ferret#nose', true], + ['urn:example:animal:ferret:nose', true], + ['ftp://ftp.is.co.za/rfc/rfc1808.txt', true], + ['http://www.ietf.org/rfc/rfc2396.txt', true], + ['ldap://[2001:db8::7]/c=GB?objectClass?one', true], + ['mailto:John.Doe@example.com', true], + ['news:comp.infosystems.www.servers.unix', true], + ['tel:+1-816-555-1212', true], + ['telnet://192.0.2.16:80/', true], + ['urn:oasis:names:specification:docbook:dtd:xml:4.1.2', true], + ['file:///example.txt', true], + ['http://asdf:qw%20er@localhost:8000?asdf=12345&asda=fc%2F#bacon', true], + ['http://asdf@localhost:8000', true], + ['http://[v1.09azAZ-._~!$&\'()*+,;=:]', true], + ['http://[a:b:c:d:e::1.2.3.4]', true], + ['coap://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]', true], + ['http://[1080:0:0:0:8:800:200C:417A]', true], + ['http://127.0.0.1:8000/foo?bar', true], + ['http://asdf:qwer@localhost:8000', true], + ['http://user:pass%3A@localhost:80', true], + ['http://localhost:123', true], + ['https://localhost:123', true], + ['file:///whatever', true], + ['mailto:asdf@asdf.com', true], + ['ftp://www.example.com', true], + ['javascript:alert(\'hello\');', true], // eslint-disable-line no-script-url + ['xmpp:isaacschlueter@jabber.org', true], + ['f://some.host/path', true], + ['http://localhost:18/asdf', true], + ['http://localhost:42/asdf?qwer=zxcv', true], + ['HTTP://www.example.com/', true], + ['HTTP://www.example.com', true], + ['http://www.ExAmPlE.com/', true], + ['http://user:pw@www.ExAmPlE.com/', true], + ['http://USER:PW@www.ExAmPlE.com/', true], + ['http://user@www.example.com/', true], + ['http://user%3Apw@www.example.com/', true], + ['http://x.com/path?that%27s#all,%20folks', true], + ['HTTP://X.COM/Y', true], + ['http://www.narwhaljs.org/blog/categories?id=news', true], + ['http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=', true], + ['http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=', true], + ['http://user:pass@mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=', true], + ['http://_jabber._tcp.google.com:80/test', true], + ['http://user:pass@_jabber._tcp.google.com:80/test', true], + ['http://[fe80::1]/a/b?a=b#abc', true], + ['http://user:password@[3ffe:2a00:100:7031::1]:8080', true], + ['coap://[1080:0:0:0:8:800:200C:417A]:61616/', true], + ['git+http://github.com/joyent/node.git', true], + ['http://bucket_name.s3.amazonaws.com/image.jpg', true], + ['dot.test://foo/bar', true], + ['svn+ssh://foo/bar', true], + ['dash-test://foo/bar', true], + ['xmpp:isaacschlueter@jabber.org', true], + ['http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar', true], + ['javascript:alert(\'hello\');', true], // eslint-disable-line no-script-url + ['file://localhost/etc/node/', true], + ['file:///etc/node/', true], + ['http://USER:PW@www.ExAmPlE.com/', true], + ['mailto:local1@domain1?query1', true], + ['http://example/a/b?c/../d', true], + ['http://example/x%2Fabc', true], + ['http://a/b/c/d;p=1/g;x=1/y', true], + ['http://a/b/c/g#s/../x', true], + ['http://a/b/c/.foo', true], + ['http://example.com/b//c//d;p?q#blarg', true], + ['g:h', true], + ['http://a/b/c/g', true], + ['http://a/b/c/g/', true], + ['http://a/g', true], + ['http://g', true], + ['http://a/b/c/d;p?y', true], + ['http://a/b/c/g?y', true], + ['http://a/b/c/d;p?q#s', true], + ['http://a/b/c/g#s', true], + ['http://a/b/c/g?y#s', true], + ['http://a/b/c/;x', true], + ['http://a/b/c/g;x', true], + ['http://a/b/c/g;x?y#s', true], + ['http://a/b/c/d;p?q', true], + ['http://a/b/c/', true], + ['http://a/b/', true], + ['http://a/b/g', true], + ['http://a/', true], + ['http://a/g', true], + ['http://a/g', true], + ['file:/asda', true], + ['qwerty', false], + ['invalid uri', false], + ['1http://google.com', false], + ['http://testdomain`,.<>/?\'";{}][++\\|~!@#$%^&*().org', false], + ['', false], + ['(╯°□°)╯︵ ┻━┻', false], + ['one/two/three?value=abc&value2=123#david-rules', false], + ['//username:password@test.example.com/one/two/three?value=abc&value2=123#david-rules', false], + ['http://a\r" \t\n<\'b:b@c\r\nd/e?f', false] + ], done); + }); + + it('validates uri with a single scheme provided', function (done) { + + var schema = Joi.string().uri({ + scheme: 'http' + }); + + Helper.validate(schema, [ + ['http://google.com', true], + ['https://google.com', false], + ['ftp://google.com', false], + ['file:/asdf', false], + ['/path?query=value#hash', false] + ], done); + }); + + it('validates uri with a single regex scheme provided', function (done) { + + var schema = Joi.string().uri({ + scheme: /https?/ + }); + + Helper.validate(schema, [ + ['http://google.com', true], + ['https://google.com', true], + ['ftp://google.com', false], + ['file:/asdf', false], + ['/path?query=value#hash', false] + ], done); + }); + + it('validates uri with multiple schemes provided', function (done) { + + var schema = Joi.string().uri({ + scheme: [/https?/, 'ftp', 'file', 'git+http'] + }); + + Helper.validate(schema, [ + ['http://google.com', true], + ['https://google.com', true], + ['ftp://google.com', true], + ['file:/asdf', true], + ['git+http://github.com/hapijs/joi', true], + ['/path?query=value#hash', false] + ], done); + }); + + it('validates uri with a friendly error message', function (done) { + + var schema = { item: Joi.string().uri() }; + + Joi.compile(schema).validate({ item: 'something invalid' }, function (err, value) { + + expect(err.message).to.contain('must be a valid uri'); + done(); + }); + }); + + it('validates uri with a custom scheme with a friendly error message', function (done) { + + var schema = { + item: Joi.string().uri({ + scheme: 'http' + }) + }; + + Joi.compile(schema).validate({ item: 'something invalid' }, function (err, value) { + + expect(err.message).to.contain('must be a valid uri with a scheme matching the http pattern'); + done(); + }); + }); + + it('validates uri with a custom array of schemes with a friendly error message', function (done) { + + var schema = { + item: Joi.string().uri({ + scheme: ['http', /https?/] + }) + }; + + Joi.compile(schema).validate({ item: 'something invalid' }, function (err, value) { + + expect(err.message).to.contain('must be a valid uri with a scheme matching the http|https? pattern'); + done(); + }); + }); + + it('validates uri treats scheme as optional', function (done) { + + expect(function () { + + Joi.string().uri({}); + }).to.not.throw(); + + done(); + }); + + it('validates uri requires uriOptions as an object with a friendly error message', function (done) { + + expect(function () { + + Joi.string().uri('http'); + }).to.throw(Error, 'options must be an object'); + + done(); + }); + + it('validates uri requires scheme to be a RegExp, String, or Array with a friendly error message', function (done) { + + expect(function () { + + Joi.string().uri({ + scheme: {} + }); + }).to.throw(Error, 'scheme must be a RegExp, String, or Array'); + + done(); + }); + + it('validates uri requires scheme to not be an empty array', function (done) { + + expect(function () { + + Joi.string().uri({ + scheme: [] + }); + }).to.throw(Error, 'scheme must have at least 1 scheme specified'); + + done(); + }); + + it('validates uri requires scheme to be an Array of schemes to all be valid schemes with a friendly error message', function (done) { + + expect(function () { + + Joi.string().uri({ + scheme: [ + 'http', + '~!@#$%^&*()_' + ] + }); + }).to.throw(Error, 'scheme at position 1 must be a valid scheme'); + + done(); + }); + + it('validates uri requires scheme to be an Array of schemes to be strings or RegExp', function (done) { + + expect(function () { + + Joi.string().uri({ + scheme: [ + 'http', + {} + ] + }); + }).to.throw(Error, 'scheme at position 1 must be a RegExp or String'); + + done(); + }); + + it('validates uri requires scheme to be a valid String scheme with a friendly error message', function (done) { + + expect(function () { + + Joi.string().uri({ + scheme: '~!@#$%^&*()_' + }); + }).to.throw(Error, 'scheme at position 0 must be a valid scheme'); + + done(); + }); + + it('validates isoDate', function (done) { + + Helper.validate(Joi.string().isoDate(), [ + ['2013-06-07T14:21:46.295Z', true], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', true], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', true], + ['2013-06-07T14:21:46Z', true], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', true], + ['2013-06-07T14:21:46+07:000', false], + ['2013-06-07T14:21:46-07:00', true], + ['2013-06-07T14:21Z', true], + ['2013-06-07T14:21+07:00', true], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', true], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', true], + ['2013-06-07T', false], + ['2013-06-07T14:21', true], + ['1-1-2013', false], + ['2013-06-07T14.2334,4', true], + ['2013-06-07T14,23:34', false], + ['2013-06-07T24', false], + ['2013-06-07T24:00', true], + ['2013-06-07T24:21', false], + ['2013-06-07 142146.295', true], + ['2013-06-07 146946.295', false], + ['2013-06-07 1421,44', true], + ['2013-W23', true], + ['2013-W23-1', true], + ['2013-W2311', false], + ['2013-W231', true], + ['2013-M231', false], + ['2013-W23-1T14:21', true], + ['2013-W23-1T14:21:', false], + ['2013-W23-1T14:21:46+07:00', true], + ['2013-W23-1T14:21:46+07:000', false], + ['2013-W23-1T14:21:46-07:00', true], + ['2013-184', true], + ['2013-1841', false] + ], done); + }); + + it('validates isoDate with a friendly error message', function (done) { + + var schema = { item: Joi.string().isoDate() }; + Joi.compile(schema).validate({ item: 'something' }, function (err, value) { + + expect(err.message).to.contain('must be a valid ISO 8601 date'); + done(); + }); + }); + + it('validates combination of isoDate and min', function (done) { + + var rule = Joi.string().isoDate().min(23); + Helper.validate(rule, [ + ['2013-06-07T14:21:46.295Z', true], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', true], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', true], + ['2013-06-07T14:21:46Z', false], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', true], + ['2013-06-07T14:21:46-07:00', true], + ['2013-06-07T14:21Z', false], + ['2013-06-07T14:21+07:00', false], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', false], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', false], + ['2013-06-07T', false], + ['2013-06-07T14:21', false], + ['1-1-2013', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of isoDate, min and max', function (done) { + + var rule = Joi.string().isoDate().min(17).max(23); + Helper.validate(rule, [ + ['2013-06-07T14:21:46.295Z', false], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', false], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', false], + ['2013-06-07T14:21:46Z', true], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', false], + ['2013-06-07T14:21:46-07:00', false], + ['2013-06-07T14:21Z', true], + ['2013-06-07T14:21+07:00', true], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', true], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', false], + ['2013-06-07T', false], + ['2013-06-07T14:21', false], + ['1-1-2013', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of isoDate, min, max and invalid', function (done) { + + var rule = Joi.string().isoDate().min(17).max(23).invalid('2013-06-07T14:21+07:00'); + Helper.validate(rule, [ + ['2013-06-07T14:21:46.295Z', false], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', false], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', false], + ['2013-06-07T14:21:46Z', true], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', false], + ['2013-06-07T14:21:46-07:00', false], + ['2013-06-07T14:21Z', true], + ['2013-06-07T14:21+07:00', false], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', true], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', false], + ['2013-06-07T', false], + ['2013-06-07T14:21', false], + ['1-1-2013', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of isoDate, min, max and allow', function (done) { + + var rule = Joi.string().isoDate().min(17).max(23).allow('2013-06-07T14:21:46.295+07:00'); + Helper.validate(rule, [ + ['2013-06-07T14:21:46.295Z', false], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', true], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', false], + ['2013-06-07T14:21:46Z', true], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', false], + ['2013-06-07T14:21:46-07:00', false], + ['2013-06-07T14:21Z', true], + ['2013-06-07T14:21+07:00', true], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', true], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', false], + ['2013-06-07T', false], + ['2013-06-07T14:21', false], + ['1-1-2013', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of isoDate, min, max, allow and invalid', function (done) { + + var rule = Joi.string().isoDate().min(17).max(23).allow('2013-06-07T14:21:46.295+07:00').invalid('2013-06-07T14:21+07:00'); + Helper.validate(rule, [ + ['2013-06-07T14:21:46.295Z', false], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', true], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', false], + ['2013-06-07T14:21:46Z', true], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', false], + ['2013-06-07T14:21:46-07:00', false], + ['2013-06-07T14:21Z', true], + ['2013-06-07T14:21+07:00', false], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', true], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', false], + ['2013-06-07T', false], + ['2013-06-07T14:21', false], + ['1-1-2013', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of isoDate, min, max, allow, invalid and allow(\'\')', function (done) { + + var rule = Joi.string().isoDate().min(17).max(23).allow('2013-06-07T14:21:46.295+07:00').invalid('2013-06-07T14:21+07:00').allow(''); + Helper.validate(rule, [ + ['2013-06-07T14:21:46.295Z', false], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', true], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', false], + ['2013-06-07T14:21:46Z', true], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', false], + ['2013-06-07T14:21:46-07:00', false], + ['2013-06-07T14:21Z', true], + ['2013-06-07T14:21+07:00', false], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', true], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', false], + ['2013-06-07T', false], + ['2013-06-07T14:21', false], + ['1-1-2013', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of isoDate, min, max, allow, invalid and allow(\'\')', function (done) { + + var rule = Joi.string().isoDate().min(17).max(23).allow('2013-06-07T14:21:46.295+07:00').allow(''); + Helper.validate(rule, [ + ['2013-06-07T14:21:46.295Z', false], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', true], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', false], + ['2013-06-07T14:21:46Z', true], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', false], + ['2013-06-07T14:21:46-07:00', false], + ['2013-06-07T14:21Z', true], + ['2013-06-07T14:21+07:00', true], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', true], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', false], + ['2013-06-07T', false], + ['2013-06-07T14:21', false], + ['1-1-2013', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of isoDate, min, max, allow, invalid and regex', function (done) { + + var rule = Joi.string().isoDate().min(17).max(23).allow('2013-06-07T14:21:46.295+07:00').invalid('2013-06-07T14:21Z').regex(/Z$/); + Helper.validate(rule, [ + ['2013-06-07T14:21:46.295Z', false], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', true], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', false], + ['2013-06-07T14:21:46Z', true], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', false], + ['2013-06-07T14:21:46-07:00', false], + ['2013-06-07T14:21Z', false], + ['2013-06-07T14:21+07:00', false], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', false], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', false], + ['2013-06-07T', false], + ['2013-06-07T14:21', false], + ['1-1-2013', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of isoDate, min, max, allow, invalid, regex and allow(\'\')', function (done) { + + var rule = Joi.string().isoDate().min(17).max(23).allow('2013-06-07T14:21:46.295+07:00').invalid('2013-06-07T14:21Z').regex(/Z$/).allow(''); + Helper.validate(rule, [ + ['2013-06-07T14:21:46.295Z', false], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', true], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', false], + ['2013-06-07T14:21:46Z', true], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', false], + ['2013-06-07T14:21:46-07:00', false], + ['2013-06-07T14:21Z', false], + ['2013-06-07T14:21+07:00', false], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', false], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', false], + ['2013-06-07T', false], + ['2013-06-07T14:21', false], + ['1-1-2013', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of isoDate, min, max and allow(\'\')', function (done) { + + var rule = Joi.string().isoDate().min(17).max(23).allow(''); + Helper.validate(rule, [ + ['2013-06-07T14:21:46.295Z', false], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', false], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', false], + ['2013-06-07T14:21:46Z', true], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', false], + ['2013-06-07T14:21:46-07:00', false], + ['2013-06-07T14:21Z', true], + ['2013-06-07T14:21+07:00', true], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', true], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', false], + ['2013-06-07T', false], + ['2013-06-07T14:21', false], + ['1-1-2013', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of isoDate, min, max and regex', function (done) { + + var rule = Joi.string().isoDate().min(17).max(23).regex(/Z$/); + Helper.validate(rule, [ + ['2013-06-07T14:21:46.295Z', false], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', false], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', false], + ['2013-06-07T14:21:46Z', true], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', false], + ['2013-06-07T14:21:46-07:00', false], + ['2013-06-07T14:21Z', true], + ['2013-06-07T14:21+07:00', false], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', false], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', false], + ['2013-06-07T', false], + ['2013-06-07T14:21', false], + ['1-1-2013', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of isoDate, min, max, regex and allow(\'\')', function (done) { + + var rule = Joi.string().isoDate().min(17).max(23).regex(/Z$/).allow(''); + Helper.validate(rule, [ + ['2013-06-07T14:21:46.295Z', false], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', false], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', false], + ['2013-06-07T14:21:46Z', true], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', false], + ['2013-06-07T14:21:46-07:00', false], + ['2013-06-07T14:21Z', true], + ['2013-06-07T14:21+07:00', false], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', false], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', false], + ['2013-06-07T', false], + ['2013-06-07T14:21', false], + ['1-1-2013', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of isoDate, min, max, regex and required', function (done) { + + var rule = Joi.string().isoDate().min(17).max(23).regex(/Z$/).required(); + Helper.validate(rule, [ + ['2013-06-07T14:21:46.295Z', false], + ['2013-06-07T14:21:46.295Z0', false], + ['2013-06-07T14:21:46.295+07:00', false], + ['2013-06-07T14:21:46.295+07:000', false], + ['2013-06-07T14:21:46.295-07:00', false], + ['2013-06-07T14:21:46Z', true], + ['2013-06-07T14:21:46Z0', false], + ['2013-06-07T14:21:46+07:00', false], + ['2013-06-07T14:21:46-07:00', false], + ['2013-06-07T14:21Z', true], + ['2013-06-07T14:21+07:00', false], + ['2013-06-07T14:21+07:000', false], + ['2013-06-07T14:21-07:00', false], + ['2013-06-07T14:21Z+7:00', false], + ['2013-06-07', false], + ['2013-06-07T', false], + ['2013-06-07T14:21', false], + ['1-1-2013', false], + ['', false], + [null, false] + ], done); + }); + + it('validates guid', function (done) { + + Helper.validate(Joi.string().guid(), [ + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', true], + ['{B59511BD6A5F4DF09ECF562A108D8A2E}', true], + ['69593D62-71EA-4548-85E4-04FC71357423', true], + ['677E2553DD4D43B09DA77414DB1EB8EA', true], + ['{5ba3bba3-729a-4717-88c1-b7c4b7ba80db}', true], + ['{7e9081b59a6d4cc1a8c347f69fb4198d}', true], + ['0c74f13f-fa83-4c48-9b33-68921dd72463', true], + ['b4b2fb69c6244e5eb0698e0c6ec66618', true], + ['{283B67B2-430F-4E6F-97E6-19041992-C1B0}', false], + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D', false], + ['D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false] + ], done); + }); + + it('validates guid with a friendly error message', function (done) { + + var schema = { item: Joi.string().guid() }; + Joi.compile(schema).validate({ item: 'something' }, function (err, value) { + + expect(err.message).to.contain('must be a valid GUID'); + done(); + }); + }); + + it('validates combination of guid and min', function (done) { + + var rule = Joi.string().guid().min(36); + Helper.validate(rule, [ + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', true], + ['{B59511BD6A5F4DF09ECF562A108D8A2E}', false], + ['69593D62-71EA-4548-85E4-04FC71357423', true], + ['677E2553DD4D43B09DA77414DB1EB8EA', false], + ['{5ba3bba3-729a-4717-88c1-b7c4b7ba80db}', true], + ['{7e9081b59a6d4cc1a8c347f69fb4198d}', false], + ['0c74f13f-fa83-4c48-9b33-68921dd72463', true], + ['b4b2fb69c6244e5eb0698e0c6ec66618', false], + ['{283B67B2-430F-4E6F-97E6-19041992-C1B0}', false], + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D', false], + ['D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of guid, min and max', function (done) { + + var rule = Joi.string().guid().min(32).max(34); + Helper.validate(rule, [ + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['{B59511BD6A5F4DF09ECF562A108D8A2E}', true], + ['69593D62-71EA-4548-85E4-04FC71357423', false], + ['677E2553DD4D43B09DA77414DB1EB8EA', true], + ['{5ba3bba3-729a-4717-88c1-b7c4b7ba80db}', false], + ['{7e9081b59a6d4cc1a8c347f69fb4198d}', true], + ['0c74f13f-fa83-4c48-9b33-68921dd72463', false], + ['b4b2fb69c6244e5eb0698e0c6ec66618', true], + ['{283B67B2-430F-4E6F-97E6-19041992-C1B0}', false], + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D', false], + ['D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of guid, min, max and invalid', function (done) { + + var rule = Joi.string().guid().min(32).max(34).invalid('b4b2fb69c6244e5eb0698e0c6ec66618'); + Helper.validate(rule, [ + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['{B59511BD6A5F4DF09ECF562A108D8A2E}', true], + ['69593D62-71EA-4548-85E4-04FC71357423', false], + ['677E2553DD4D43B09DA77414DB1EB8EA', true], + ['{5ba3bba3-729a-4717-88c1-b7c4b7ba80db}', false], + ['{7e9081b59a6d4cc1a8c347f69fb4198d}', true], + ['0c74f13f-fa83-4c48-9b33-68921dd72463', false], + ['b4b2fb69c6244e5eb0698e0c6ec66618', false], + ['{283B67B2-430F-4E6F-97E6-19041992-C1B0}', false], + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D', false], + ['D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of guid, min, max and allow', function (done) { + + var rule = Joi.string().guid().min(32).max(34).allow('{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D'); + Helper.validate(rule, [ + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['{B59511BD6A5F4DF09ECF562A108D8A2E}', true], + ['69593D62-71EA-4548-85E4-04FC71357423', false], + ['677E2553DD4D43B09DA77414DB1EB8EA', true], + ['{5ba3bba3-729a-4717-88c1-b7c4b7ba80db}', false], + ['{7e9081b59a6d4cc1a8c347f69fb4198d}', true], + ['0c74f13f-fa83-4c48-9b33-68921dd72463', false], + ['b4b2fb69c6244e5eb0698e0c6ec66618', true], + ['{283B67B2-430F-4E6F-97E6-19041992-C1B0}', false], + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D', true], + ['D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of guid, min, max, allow and invalid', function (done) { + + var rule = Joi.string().guid().min(32).max(34).allow('{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D').invalid('b4b2fb69c6244e5eb0698e0c6ec66618'); + Helper.validate(rule, [ + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['{B59511BD6A5F4DF09ECF562A108D8A2E}', true], + ['69593D62-71EA-4548-85E4-04FC71357423', false], + ['677E2553DD4D43B09DA77414DB1EB8EA', true], + ['{5ba3bba3-729a-4717-88c1-b7c4b7ba80db}', false], + ['{7e9081b59a6d4cc1a8c347f69fb4198d}', true], + ['0c74f13f-fa83-4c48-9b33-68921dd72463', false], + ['b4b2fb69c6244e5eb0698e0c6ec66618', false], + ['{283B67B2-430F-4E6F-97E6-19041992-C1B0}', false], + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D', true], + ['D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of guid, min, max, allow, invalid and allow(\'\')', function (done) { + + var rule = Joi.string().guid().min(32).max(34).allow('{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D').invalid('b4b2fb69c6244e5eb0698e0c6ec66618').allow(''); + Helper.validate(rule, [ + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['{B59511BD6A5F4DF09ECF562A108D8A2E}', true], + ['69593D62-71EA-4548-85E4-04FC71357423', false], + ['677E2553DD4D43B09DA77414DB1EB8EA', true], + ['{5ba3bba3-729a-4717-88c1-b7c4b7ba80db}', false], + ['{7e9081b59a6d4cc1a8c347f69fb4198d}', true], + ['0c74f13f-fa83-4c48-9b33-68921dd72463', false], + ['b4b2fb69c6244e5eb0698e0c6ec66618', false], + ['{283B67B2-430F-4E6F-97E6-19041992-C1B0}', false], + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D', true], + ['D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of guid, min, max, allow and allow(\'\')', function (done) { + + var rule = Joi.string().guid().min(32).max(34).allow('{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D').allow(''); + Helper.validate(rule, [ + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['{B59511BD6A5F4DF09ECF562A108D8A2E}', true], + ['69593D62-71EA-4548-85E4-04FC71357423', false], + ['677E2553DD4D43B09DA77414DB1EB8EA', true], + ['{5ba3bba3-729a-4717-88c1-b7c4b7ba80db}', false], + ['{7e9081b59a6d4cc1a8c347f69fb4198d}', true], + ['0c74f13f-fa83-4c48-9b33-68921dd72463', false], + ['b4b2fb69c6244e5eb0698e0c6ec66618', true], + ['{283B67B2-430F-4E6F-97E6-19041992-C1B0}', false], + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D', true], + ['D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of guid, min, max, allow, invalid and regex', function (done) { + + var rule = Joi.string().guid().min(32).max(34).allow('{D1A5279D-B27D-4CD4-A05E-EFDD53D08').invalid('b4b2fb69c6244e5eb0698e0c6ec66618').regex(/^{7e908/); + Helper.validate(rule, [ + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['{B59511BD6A5F4DF09ECF562A108D8A2E}', false], + ['69593D62-71EA-4548-85E4-04FC71357423', false], + ['677E2553DD4D43B09DA77414DB1EB8EA', false], + ['{5ba3bba3-729a-4717-88c1-b7c4b7ba80db}', false], + ['{7e9081b59a6d4cc1a8c347f69fb4198d}', true], + ['0c74f13f-fa83-4c48-9b33-68921dd72463', false], + ['b4b2fb69c6244e5eb0698e0c6ec66618', false], + ['{283B67B2-430F-4E6F-97E6-19041992-C1B0}', false], + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08', true], + ['D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of guid, min, max, allow, invalid, regex and allow(\'\')', function (done) { + + var rule = Joi.string().guid().min(32).max(34).allow('{D1A5279D-B27D-4CD4-A05E-EFDD53D08').invalid('b4b2fb69c6244e5eb0698e0c6ec66618').regex(/^{7e908/).allow(''); + Helper.validate(rule, [ + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['{B59511BD6A5F4DF09ECF562A108D8A2E}', false], + ['69593D62-71EA-4548-85E4-04FC71357423', false], + ['677E2553DD4D43B09DA77414DB1EB8EA', false], + ['{5ba3bba3-729a-4717-88c1-b7c4b7ba80db}', false], + ['{7e9081b59a6d4cc1a8c347f69fb4198d}', true], + ['0c74f13f-fa83-4c48-9b33-68921dd72463', false], + ['b4b2fb69c6244e5eb0698e0c6ec66618', false], + ['{283B67B2-430F-4E6F-97E6-19041992-C1B0}', false], + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08', true], + ['D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of guid, min, max and allow(\'\')', function (done) { + + var rule = Joi.string().guid().min(32).max(34).allow(''); + Helper.validate(rule, [ + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['{B59511BD6A5F4DF09ECF562A108D8A2E}', true], + ['69593D62-71EA-4548-85E4-04FC71357423', false], + ['677E2553DD4D43B09DA77414DB1EB8EA', true], + ['{5ba3bba3-729a-4717-88c1-b7c4b7ba80db}', false], + ['{7e9081b59a6d4cc1a8c347f69fb4198d}', true], + ['0c74f13f-fa83-4c48-9b33-68921dd72463', false], + ['b4b2fb69c6244e5eb0698e0c6ec66618', true], + ['{283B67B2-430F-4E6F-97E6-19041992-C1B0}', false], + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D', false], + ['D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of guid, min, max and regex', function (done) { + + var rule = Joi.string().guid().min(32).max(34).regex(/^{7e9081/i); + Helper.validate(rule, [ + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['{B59511BD6A5F4DF09ECF562A108D8A2E}', false], + ['69593D62-71EA-4548-85E4-04FC71357423', false], + ['677E2553DD4D43B09DA77414DB1EB8EA', false], + ['{5ba3bba3-729a-4717-88c1-b7c4b7ba80db}', false], + ['{7e9081b59a6d4cc1a8c347f69fb4198d}', true], + ['0c74f13f-fa83-4c48-9b33-68921dd72463', false], + ['b4b2fb69c6244e5eb0698e0c6ec66618', false], + ['{283B67B2-430F-4E6F-97E6-19041992-C1B0}', false], + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D', false], + ['D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['', false], + [null, false] + ], done); + }); + + it('validates combination of guid, min, max, regex and allow(\'\')', function (done) { + + var rule = Joi.string().guid().min(32).max(34).regex(/^{7e9081/i).allow(''); + Helper.validate(rule, [ + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['{B59511BD6A5F4DF09ECF562A108D8A2E}', false], + ['69593D62-71EA-4548-85E4-04FC71357423', false], + ['677E2553DD4D43B09DA77414DB1EB8EA', false], + ['{5ba3bba3-729a-4717-88c1-b7c4b7ba80db}', false], + ['{7e9081b59a6d4cc1a8c347f69fb4198d}', true], + ['0c74f13f-fa83-4c48-9b33-68921dd72463', false], + ['b4b2fb69c6244e5eb0698e0c6ec66618', false], + ['{283B67B2-430F-4E6F-97E6-19041992-C1B0}', false], + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D', false], + ['D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['', true], + [null, false] + ], done); + }); + + it('validates combination of guid, min, max, regex and required', function (done) { + + var rule = Joi.string().guid().min(32).max(34).regex(/^{7e9081/i).required(); + Helper.validate(rule, [ + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['{B59511BD6A5F4DF09ECF562A108D8A2E}', false], + ['69593D62-71EA-4548-85E4-04FC71357423', false], + ['677E2553DD4D43B09DA77414DB1EB8EA', false], + ['{5ba3bba3-729a-4717-88c1-b7c4b7ba80db}', false], + ['{7e9081b59a6d4cc1a8c347f69fb4198d}', true], + ['0c74f13f-fa83-4c48-9b33-68921dd72463', false], + ['b4b2fb69c6244e5eb0698e0c6ec66618', false], + ['{283B67B2-430F-4E6F-97E6-19041992-C1B0}', false], + ['{D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D', false], + ['D1A5279D-B27D-4CD4-A05E-EFDD53D08E8D}', false], + ['', false], + [null, false] + ], done); + }); + + it('validates an hexadecimal string', function (done) { + + var rule = Joi.string().hex(); + Helper.validate(rule, [ + ['123456789abcdef', true], + ['123456789AbCdEf', true], + ['123afg', false, null, '"value" must only contain hexadecimal characters'] + ], done); + }); + }); +});
@@ -0,0 +1,11 @@
+{ + "freeze": true, + "latedef": "nofunc", + "undef": true, + "unused": true, + "trailing": true, + "immed": true, + "predef": ["console", "require", "__dirname"], + "esnext": true, + "lastsemic": true +}
@@ -0,0 +1,4 @@
+node_modules +/test/keys +/test/*.pem +/test/encrypted-key-passphrase
@@ -0,0 +1,6 @@
+language: node_js +node_js: + - 0.10 + - 0.12 + - 4 + - 5
@@ -0,0 +1,34 @@
+# Change Log +All notable changes to this project will be documented in this file. + +## [3.0.0] +### Changed +- **BREAKING**: `jwt.verify` now requires an `algorithm` parameter, and + `jws.createVerify` requires an `algorithm` option. The `"alg"` field + signature headers is ignored. This mitigates a critical security flaw + in the library which would allow an attacker to generate signatures with + arbitrary contents that would be accepted by `jwt.verify`. See + https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/ + for details. + +## [2.0.0] - 2015-01-30 +### Changed +- **BREAKING**: Default payload encoding changed from `binary` to + `utf8`. `utf8` is a is a more sensible default than `binary` because + many payloads, as far as I can tell, will contain user-facing + strings that could be in any language. (<code>[6b6de48]</code>) + +- Code reorganization, thanks [@fearphage]! (<code>[7880050]</code>) + +### Added +- Option in all relevant methods for `encoding`. For those few users + that might be depending on a `binary` encoding of the messages, this + is for them. (<code>[6b6de48]</code>) + +[unreleased]: https://github.com/brianloveswords/node-jws/compare/v2.0.0...HEAD +[2.0.0]: https://github.com/brianloveswords/node-jws/compare/v1.0.1...v2.0.0 + +[7880050]: https://github.com/brianloveswords/node-jws/commit/7880050 +[6b6de48]: https://github.com/brianloveswords/node-jws/commit/6b6de48 + +[@fearphage]: https://github.com/fearphage
@@ -0,0 +1,17 @@
+Copyright (c) 2013 Brian J. Brennan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,32 @@
+verbose: test/keys + @node test/*.test.js + +test: test/keys + @./node_modules/.bin/tape test/*.test.js + +test/keys: + @openssl genrsa 2048 > test/rsa-private.pem + @openssl genrsa 2048 > test/rsa-wrong-private.pem + @openssl rsa -in test/rsa-private.pem -pubout > test/rsa-public.pem + @openssl rsa -in test/rsa-wrong-private.pem -pubout > test/rsa-wrong-public.pem + @openssl ecparam -out test/ec256-private.pem -name secp256r1 -genkey + @openssl ecparam -out test/ec256-wrong-private.pem -name secp256k1 -genkey + @openssl ecparam -out test/ec384-private.pem -name secp384r1 -genkey + @openssl ecparam -out test/ec384-wrong-private.pem -name secp384r1 -genkey + @openssl ecparam -out test/ec512-private.pem -name secp521r1 -genkey + @openssl ecparam -out test/ec512-wrong-private.pem -name secp521r1 -genkey + @openssl ec -in test/ec256-private.pem -pubout > test/ec256-public.pem + @openssl ec -in test/ec256-wrong-private.pem -pubout > test/ec256-wrong-public.pem + @openssl ec -in test/ec384-private.pem -pubout > test/ec384-public.pem + @openssl ec -in test/ec384-wrong-private.pem -pubout > test/ec384-wrong-public.pem + @openssl ec -in test/ec512-private.pem -pubout > test/ec512-public.pem + @openssl ec -in test/ec512-wrong-private.pem -pubout > test/ec512-wrong-public.pem + @echo foo > test/encrypted-key-passphrase + @openssl rsa -passin file:test/encrypted-key-passphrase -in test/rsa-private.pem > test/rsa-private-encrypted.pem + @touch test/keys + +clean: + @rm test/*.pem + @rm test/keys + +.PHONY: test
@@ -0,0 +1,21 @@
+/*global exports*/ +var SignStream = require('./lib/sign-stream'); +var VerifyStream = require('./lib/verify-stream'); + +var ALGORITHMS = [ + 'HS256', 'HS384', 'HS512', + 'RS256', 'RS384', 'RS512', + 'ES256', 'ES384', 'ES512' +]; + +exports.ALGORITHMS = ALGORITHMS; +exports.sign = SignStream.sign; +exports.verify = VerifyStream.verify; +exports.decode = VerifyStream.decode; +exports.isValid = VerifyStream.isValid; +exports.createSign = function createSign(opts) { + return new SignStream(opts); +}; +exports.createVerify = function createVerify(opts) { + return new VerifyStream(opts); +};
@@ -0,0 +1,55 @@
+/*global module, process*/ +var Buffer = require('buffer').Buffer; +var Stream = require('stream'); +var util = require('util'); + +function DataStream(data) { + this.buffer = null; + this.writable = true; + this.readable = true; + + // No input + if (!data) { + this.buffer = new Buffer(0); + return this; + } + + // Stream + if (typeof data.pipe === 'function') { + this.buffer = new Buffer(0); + data.pipe(this); + return this; + } + + // Buffer or String + // or Object (assumedly a passworded key) + if (data.length || typeof data === 'object') { + this.buffer = data; + this.writable = false; + process.nextTick(function () { + this.emit('end', data); + this.readable = false; + this.emit('close'); + }.bind(this)); + return this; + } + + throw new TypeError('Unexpected data type ('+ typeof data + ')'); +} +util.inherits(DataStream, Stream); + +DataStream.prototype.write = function write(data) { + this.buffer = Buffer.concat([this.buffer, Buffer(data)]); + this.emit('data', data); +}; + +DataStream.prototype.end = function end(data) { + if (data) + this.write(data); + this.emit('end', data); + this.emit('close'); + this.writable = false; + this.readable = false; +}; + +module.exports = DataStream;
@@ -0,0 +1,69 @@
+/*global module*/ +var base64url = require('base64url'); +var DataStream = require('./data-stream'); +var jwa = require('jwa'); +var Stream = require('stream'); +var toString = require('./tostring'); +var util = require('util'); + +function jwsSecuredInput(header, payload, encoding) { + encoding = encoding || 'utf8'; + var encodedHeader = base64url(toString(header), 'binary'); + var encodedPayload = base64url(toString(payload), encoding); + return util.format('%s.%s', encodedHeader, encodedPayload); +} + +function jwsSign(opts) { + var header = opts.header; + var payload = opts.payload; + var secretOrKey = opts.secret || opts.privateKey; + var encoding = opts.encoding; + var algo = jwa(header.alg); + var securedInput = jwsSecuredInput(header, payload, encoding); + var signature = algo.sign(securedInput, secretOrKey); + return util.format('%s.%s', securedInput, signature); +} + +function SignStream(opts) { + var secret = opts.secret||opts.privateKey||opts.key; + var secretStream = new DataStream(secret); + this.readable = true; + this.header = opts.header; + this.encoding = opts.encoding; + this.secret = this.privateKey = this.key = secretStream; + this.payload = new DataStream(opts.payload); + this.secret.once('close', function () { + if (!this.payload.writable && this.readable) + this.sign(); + }.bind(this)); + + this.payload.once('close', function () { + if (!this.secret.writable && this.readable) + this.sign(); + }.bind(this)); +} +util.inherits(SignStream, Stream); + +SignStream.prototype.sign = function sign() { + try { + var signature = jwsSign({ + header: this.header, + payload: this.payload.buffer, + secret: this.secret.buffer, + encoding: this.encoding + }); + this.emit('done', signature); + this.emit('data', signature); + this.emit('end'); + this.readable = false; + return signature; + } catch (e) { + this.readable = false; + this.emit('error', e); + this.emit('close'); + } +}; + +SignStream.sign = jwsSign; + +module.exports = SignStream;
@@ -0,0 +1,10 @@
+/*global module*/ +var Buffer = require('buffer').Buffer; + +module.exports = function toString(obj) { + if (typeof obj === 'string') + return obj; + if (typeof obj === 'number' || Buffer.isBuffer(obj)) + return obj.toString(); + return JSON.stringify(obj); +};
@@ -0,0 +1,120 @@
+/*global module*/ +var base64url = require('base64url'); +var DataStream = require('./data-stream'); +var jwa = require('jwa'); +var Stream = require('stream'); +var toString = require('./tostring'); +var util = require('util'); +var JWS_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/; + +function isObject(thing) { + return Object.prototype.toString.call(thing) === '[object Object]'; +} + +function safeJsonParse(thing) { + if (isObject(thing)) + return thing; + try { return JSON.parse(thing); } + catch (e) { return undefined; } +} + +function headerFromJWS(jwsSig) { + var encodedHeader = jwsSig.split('.', 1)[0]; + return safeJsonParse(base64url.decode(encodedHeader, 'binary')); +} + +function securedInputFromJWS(jwsSig) { + return jwsSig.split('.', 2).join('.'); +} + +function signatureFromJWS(jwsSig) { + return jwsSig.split('.')[2]; +} + +function payloadFromJWS(jwsSig, encoding) { + encoding = encoding || 'utf8'; + var payload = jwsSig.split('.')[1]; + return base64url.decode(payload, encoding); +} + +function isValidJws(string) { + return JWS_REGEX.test(string) && !!headerFromJWS(string); +} + +function jwsVerify(jwsSig, algorithm, secretOrKey) { + if (!algorithm) { + var err = new Error("Missing algorithm parameter for jws.verify"); + err.code = "MISSING_ALGORITHM"; + throw err; + } + jwsSig = toString(jwsSig); + var signature = signatureFromJWS(jwsSig); + var securedInput = securedInputFromJWS(jwsSig); + var algo = jwa(algorithm); + return algo.verify(securedInput, signature, secretOrKey); +} + +function jwsDecode(jwsSig, opts) { + opts = opts || {}; + jwsSig = toString(jwsSig); + + if (!isValidJws(jwsSig)) + return null; + + var header = headerFromJWS(jwsSig); + + if (!header) + return null; + + var payload = payloadFromJWS(jwsSig); + if (header.typ === 'JWT' || opts.json) + payload = JSON.parse(payload, opts.encoding); + + return { + header: header, + payload: payload, + signature: signatureFromJWS(jwsSig) + }; +} + +function VerifyStream(opts) { + opts = opts || {}; + var secretOrKey = opts.secret||opts.publicKey||opts.key; + var secretStream = new DataStream(secretOrKey); + this.readable = true; + this.algorithm = opts.algorithm; + this.encoding = opts.encoding; + this.secret = this.publicKey = this.key = secretStream; + this.signature = new DataStream(opts.signature); + this.secret.once('close', function () { + if (!this.signature.writable && this.readable) + this.verify(); + }.bind(this)); + + this.signature.once('close', function () { + if (!this.secret.writable && this.readable) + this.verify(); + }.bind(this)); +} +util.inherits(VerifyStream, Stream); +VerifyStream.prototype.verify = function verify() { + try { + var valid = jwsVerify(this.signature.buffer, this.algorithm, this.key.buffer); + var obj = jwsDecode(this.signature.buffer, this.encoding); + this.emit('done', valid, obj); + this.emit('data', valid); + this.emit('end'); + this.readable = false; + return valid; + } catch (e) { + this.readable = false; + this.emit('error', e); + this.emit('close'); + } +}; + +VerifyStream.decode = jwsDecode; +VerifyStream.isValid = isValidJws; +VerifyStream.verify = jwsVerify; + +module.exports = VerifyStream;
@@ -0,0 +1,1 @@
+../base64url/bin/base64url
@@ -0,0 +1,1 @@
+node_modules
@@ -0,0 +1,3 @@
+language: node_js +node_js: + - 0.10
@@ -0,0 +1,20 @@
+Copyright (c) 2013 Brian J. Brennan + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,105 @@
+#!/usr/bin/env node + +var fs = require('fs'); +var concat = require('concat-stream'); +var base64url = require('../'); +var cli = require('meow')({ + pkg: '../package.json', + help: [ + 'Usage: base64url [-hvD] [-b num] [-i in_file] [-o out_file]', + ' -h, --help display this message', + ' -v, --version display version info', + ' -D, --decode decodes input', + ' -b, --break break encoded string into num character lines', + ' -i, --input input file (default: stdin)', + ' -o, --output output file (default: stdout)' + ].join('\n') +}, { + boolean: [ + 'D', 'decode', + 'h', 'help', + 'v', 'version', + ], + string: [ + 'i', 'input', + 'o', 'output', + 'b', 'break', + ], +}); + +var decode = cli.flags.d || cli.flags.decode; +var fn = decode && base64url.decode || base64url.encode; + +function processStream(outputStream, breakLength) { + outputStream = outputStream || process.stdout; + return concat(function (buf) { + outputStream.write(format(fn(buf), breakLength)); + process.exit(0); + }); +} + +function format(string, breakLength) { + if (!breakLength) + return string; + var regex = new RegExp('(.{' + breakLength + '})', 'g'); + return string.replace(regex, '$1\n'); +} + +function main() { + var help = cli.flags.h || cli.flags.help; + var version = cli.flags.v || cli.flags.version; + + if (help) { + return cli.showHelp(); + } + + if (version) { + console.log(cli.pkg.version); + process.exit(0); + } + + var breakLines = parseInt(cli.flags.b || cli.flags.break, 10); + var inputFile = cli.flags.i || cli.flags.input; + var outputFile = cli.flags.o || cli.flags.output; + var writeStream = process.stdout; + + if (Array.isArray(inputFile)) + inputFile = inputFile.pop(); + + if (cli.input.length > 0) + inputFile = cli.input.pop(); + + if (outputFile) { + writeStream = fs.createWriteStream(outputFile); + writeStream.on('error', fileStreamErrHandler(outputFile)); + } + + var outStream = processStream(writeStream, breakLines); + + if (!inputFile) { + return process.stdin.pipe(outStream); + } + + var readStream = fs.createReadStream(inputFile); + readStream.on('error', fileStreamErrHandler(inputFile)); + + return readStream.pipe(outStream); +} + +function fileStreamErrHandler(file) { + return function (err) { + switch (err.code) { + case 'ENOENT': + console.error('Unable to open \'%s\': No such file or directory', file); + break; + case 'EISDIR': + console.error('Unable to process \'%s\': Cannot operate on directories', file); + break; + } + + process.exit(err.errno || 1); + console.log(err); + }; +} + +main();
@@ -0,0 +1,54 @@
+function fromBase64(base64string) { + return ( + base64string + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_') + ); +} + +function toBase64(base64UrlString) { + if (Buffer.isBuffer(base64UrlString)) + base64UrlString = base64UrlString.toString(); + + var b64str = padString(base64UrlString) + .replace(/\-/g, '+') + .replace(/_/g, '/'); + return b64str; +} + +function padString(string) { + var segmentLength = 4; + var stringLength = string.length; + var diff = string.length % segmentLength; + if (!diff) + return string; + var position = stringLength; + var padLength = segmentLength - diff; + var paddedStringLength = stringLength + padLength; + var buffer = Buffer(paddedStringLength); + buffer.write(string); + while (padLength--) + buffer.write('=', position++); + return buffer.toString(); +} + +function decodeBase64Url(base64UrlString, encoding) { + return Buffer(toBase64(base64UrlString), 'base64').toString(encoding); +} + +function base64url(stringOrBuffer, encoding) { + return fromBase64(Buffer(stringOrBuffer, encoding).toString('base64')); +} + +function toBuffer(base64string) { + return Buffer(toBase64(base64string), 'base64'); +} + +base64url.toBase64 = toBase64; +base64url.fromBase64 = fromBase64; +base64url.decode = decodeBase64Url; +base64url.encode = base64url; +base64url.toBuffer = toBuffer; + +module.exports = base64url;
@@ -0,0 +1,24 @@
+The MIT License + +Copyright (c) 2013 Max Ogden + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,136 @@
+var Writable = require('readable-stream').Writable +var inherits = require('inherits') + +if (typeof Uint8Array === 'undefined') { + var U8 = require('typedarray').Uint8Array +} else { + var U8 = Uint8Array +} + +function ConcatStream(opts, cb) { + if (!(this instanceof ConcatStream)) return new ConcatStream(opts, cb) + + if (typeof opts === 'function') { + cb = opts + opts = {} + } + if (!opts) opts = {} + + var encoding = opts.encoding + var shouldInferEncoding = false + + if (!encoding) { + shouldInferEncoding = true + } else { + encoding = String(encoding).toLowerCase() + if (encoding === 'u8' || encoding === 'uint8') { + encoding = 'uint8array' + } + } + + Writable.call(this, { objectMode: true }) + + this.encoding = encoding + this.shouldInferEncoding = shouldInferEncoding + + if (cb) this.on('finish', function () { cb(this.getBody()) }) + this.body = [] +} + +module.exports = ConcatStream +inherits(ConcatStream, Writable) + +ConcatStream.prototype._write = function(chunk, enc, next) { + this.body.push(chunk) + next() +} + +ConcatStream.prototype.inferEncoding = function (buff) { + var firstBuffer = buff === undefined ? this.body[0] : buff; + if (Buffer.isBuffer(firstBuffer)) return 'buffer' + if (typeof Uint8Array !== 'undefined' && firstBuffer instanceof Uint8Array) return 'uint8array' + if (Array.isArray(firstBuffer)) return 'array' + if (typeof firstBuffer === 'string') return 'string' + if (Object.prototype.toString.call(firstBuffer) === "[object Object]") return 'object' + return 'buffer' +} + +ConcatStream.prototype.getBody = function () { + if (!this.encoding && this.body.length === 0) return [] + if (this.shouldInferEncoding) this.encoding = this.inferEncoding() + if (this.encoding === 'array') return arrayConcat(this.body) + if (this.encoding === 'string') return stringConcat(this.body) + if (this.encoding === 'buffer') return bufferConcat(this.body) + if (this.encoding === 'uint8array') return u8Concat(this.body) + return this.body +} + +var isArray = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) == '[object Array]' +} + +function isArrayish (arr) { + return /Array\]$/.test(Object.prototype.toString.call(arr)) +} + +function stringConcat (parts) { + var strings = [] + var needsToString = false + for (var i = 0; i < parts.length; i++) { + var p = parts[i] + if (typeof p === 'string') { + strings.push(p) + } else if (Buffer.isBuffer(p)) { + strings.push(p) + } else { + strings.push(Buffer(p)) + } + } + if (Buffer.isBuffer(parts[0])) { + strings = Buffer.concat(strings) + strings = strings.toString('utf8') + } else { + strings = strings.join('') + } + return strings +} + +function bufferConcat (parts) { + var bufs = [] + for (var i = 0; i < parts.length; i++) { + var p = parts[i] + if (Buffer.isBuffer(p)) { + bufs.push(p) + } else if (typeof p === 'string' || isArrayish(p) + || (p && typeof p.subarray === 'function')) { + bufs.push(Buffer(p)) + } else bufs.push(Buffer(String(p))) + } + return Buffer.concat(bufs) +} + +function arrayConcat (parts) { + var res = [] + for (var i = 0; i < parts.length; i++) { + res.push.apply(res, parts[i]) + } + return res +} + +function u8Concat (parts) { + var len = 0 + for (var i = 0; i < parts.length; i++) { + if (typeof parts[i] === 'string') { + parts[i] = Buffer(parts[i]) + } + len += parts[i].length + } + var u8 = new U8(len) + for (var i = 0, offset = 0; i < parts.length; i++) { + var part = parts[i] + for (var j = 0; j < part.length; j++) { + u8[offset++] = part[j] + } + } + return u8 +}
@@ -0,0 +1,16 @@
+The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +
@@ -0,0 +1,42 @@
+Browser-friendly inheritance fully compatible with standard node.js +[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor). + +This package exports standard `inherits` from node.js `util` module in +node environment, but also provides alternative browser-friendly +implementation through [browser +field](https://gist.github.com/shtylman/4339901). Alternative +implementation is a literal copy of standard one located in standalone +module to avoid requiring of `util`. It also has a shim for old +browsers with no `Object.create` support. + +While keeping you sure you are using standard `inherits` +implementation in node.js environment, it allows bundlers such as +[browserify](https://github.com/substack/node-browserify) to not +include full `util` package to your client code if all you need is +just `inherits` function. It worth, because browser shim for `util` +package is large and `inherits` is often the single function you need +from it. + +It's recommended to use this package instead of +`require('util').inherits` for any code that has chances to be used +not only in node.js but in browser too. + +## usage + +```js +var inherits = require('inherits'); +// then use exactly as the standard one +``` + +## note on version ~1.0 + +Version ~1.0 had completely different motivation and is not compatible +neither with 2.0 nor with standard node.js `inherits`. + +If you are using version ~1.0 and planning to switch to ~2.0, be +careful: + +* new version uses `super_` instead of `super` for referencing + superclass +* new version overwrites current prototype while old one preserves any + existing fields on it
@@ -0,0 +1,1 @@
+module.exports = require('util').inherits
@@ -0,0 +1,23 @@
+if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +}
@@ -0,0 +1,50 @@
+{ + "name": "inherits", + "description": "Browser-friendly inheritance fully compatible with standard node.js inherits()", + "version": "2.0.1", + "keywords": [ + "inheritance", + "class", + "klass", + "oop", + "object-oriented", + "inherits", + "browser", + "browserify" + ], + "main": "./inherits.js", + "browser": "./inherits_browser.js", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/inherits.git" + }, + "license": "ISC", + "scripts": { + "test": "node test" + }, + "bugs": { + "url": "https://github.com/isaacs/inherits/issues" + }, + "_id": "inherits@2.0.1", + "dist": { + "shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1", + "tarball": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + }, + "_from": "inherits@>=2.0.1 <2.1.0", + "_npmVersion": "1.3.8", + "_npmUser": { + "name": "isaacs", + "email": "i@izs.me" + }, + "maintainers": [ + { + "name": "isaacs", + "email": "i@izs.me" + } + ], + "directories": {}, + "_shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1", + "_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "readme": "ERROR: No README data found!", + "homepage": "https://github.com/isaacs/inherits#readme" +}
@@ -0,0 +1,25 @@
+var inherits = require('./inherits.js') +var assert = require('assert') + +function test(c) { + assert(c.constructor === Child) + assert(c.constructor.super_ === Parent) + assert(Object.getPrototypeOf(c) === Child.prototype) + assert(Object.getPrototypeOf(Object.getPrototypeOf(c)) === Parent.prototype) + assert(c instanceof Child) + assert(c instanceof Parent) +} + +function Child() { + Parent.call(this) + test(this) +} + +function Parent() {} + +inherits(Child, Parent) + +var c = new Child +test(c) + +console.log('ok')
@@ -0,0 +1,5 @@
+build/ +test/ +examples/ +fs.js +zlib.js
@@ -0,0 +1,18 @@
+Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE.
@@ -0,0 +1,15 @@
+# readable-stream + +***Node-core streams for userland*** + +[](https://nodei.co/npm/readable-stream/) +[](https://nodei.co/npm/readable-stream/) + +This package is a mirror of the Streams2 and Streams3 implementations in Node-core. + +If you want to guarantee a stable streams base, regardless of what version of Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core. + +**readable-stream** comes in two major versions, v1.0.x and v1.1.x. The former tracks the Streams2 implementation in Node 0.10, including bug-fixes and minor improvements as they are added. The latter tracks Streams3 as it develops in Node 0.11; we will likely see a v1.2.x branch for Node 0.12. + +**readable-stream** uses proper patch-level versioning so if you pin to `"~1.0.0"` you’ll get the latest Node 0.10 Streams2 implementation, including any fixes and minor non-breaking improvements. The patch-level versions of 1.0.x and 1.1.x should mirror the patch-level versions of Node-core releases. You should prefer the **1.0.x** releases for now and when you’re ready to start using Streams3, pin to `"~1.1.0"` +
@@ -0,0 +1,1 @@
+module.exports = require("./lib/_stream_duplex.js")
@@ -0,0 +1,923 @@
+diff --git a/lib/_stream_duplex.js b/lib/_stream_duplex.js +index c5a741c..a2e0d8e 100644 +--- a/lib/_stream_duplex.js ++++ b/lib/_stream_duplex.js +@@ -26,8 +26,8 @@ + + module.exports = Duplex; + var util = require('util'); +-var Readable = require('_stream_readable'); +-var Writable = require('_stream_writable'); ++var Readable = require('./_stream_readable'); ++var Writable = require('./_stream_writable'); + + util.inherits(Duplex, Readable); + +diff --git a/lib/_stream_passthrough.js b/lib/_stream_passthrough.js +index a5e9864..330c247 100644 +--- a/lib/_stream_passthrough.js ++++ b/lib/_stream_passthrough.js +@@ -25,7 +25,7 @@ + + module.exports = PassThrough; + +-var Transform = require('_stream_transform'); ++var Transform = require('./_stream_transform'); + var util = require('util'); + util.inherits(PassThrough, Transform); + +diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js +index 0c3fe3e..90a8298 100644 +--- a/lib/_stream_readable.js ++++ b/lib/_stream_readable.js +@@ -23,10 +23,34 @@ module.exports = Readable; + Readable.ReadableState = ReadableState; + + var EE = require('events').EventEmitter; ++if (!EE.listenerCount) EE.listenerCount = function(emitter, type) { ++ return emitter.listeners(type).length; ++}; ++ ++if (!global.setImmediate) global.setImmediate = function setImmediate(fn) { ++ return setTimeout(fn, 0); ++}; ++if (!global.clearImmediate) global.clearImmediate = function clearImmediate(i) { ++ return clearTimeout(i); ++}; ++ + var Stream = require('stream'); + var util = require('util'); ++if (!util.isUndefined) { ++ var utilIs = require('core-util-is'); ++ for (var f in utilIs) { ++ util[f] = utilIs[f]; ++ } ++} + var StringDecoder; +-var debug = util.debuglog('stream'); ++var debug; ++if (util.debuglog) ++ debug = util.debuglog('stream'); ++else try { ++ debug = require('debuglog')('stream'); ++} catch (er) { ++ debug = function() {}; ++} + + util.inherits(Readable, Stream); + +@@ -380,7 +404,7 @@ function chunkInvalid(state, chunk) { + + + function onEofChunk(stream, state) { +- if (state.decoder && !state.ended) { ++ if (state.decoder && !state.ended && state.decoder.end) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); +diff --git a/lib/_stream_transform.js b/lib/_stream_transform.js +index b1f9fcc..b0caf57 100644 +--- a/lib/_stream_transform.js ++++ b/lib/_stream_transform.js +@@ -64,8 +64,14 @@ + + module.exports = Transform; + +-var Duplex = require('_stream_duplex'); ++var Duplex = require('./_stream_duplex'); + var util = require('util'); ++if (!util.isUndefined) { ++ var utilIs = require('core-util-is'); ++ for (var f in utilIs) { ++ util[f] = utilIs[f]; ++ } ++} + util.inherits(Transform, Duplex); + + +diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js +index ba2e920..f49288b 100644 +--- a/lib/_stream_writable.js ++++ b/lib/_stream_writable.js +@@ -27,6 +27,12 @@ module.exports = Writable; + Writable.WritableState = WritableState; + + var util = require('util'); ++if (!util.isUndefined) { ++ var utilIs = require('core-util-is'); ++ for (var f in utilIs) { ++ util[f] = utilIs[f]; ++ } ++} + var Stream = require('stream'); + + util.inherits(Writable, Stream); +@@ -119,7 +125,7 @@ function WritableState(options, stream) { + function Writable(options) { + // Writable ctor is applied to Duplexes, though they're not + // instanceof Writable, they're instanceof Readable. +- if (!(this instanceof Writable) && !(this instanceof Stream.Duplex)) ++ if (!(this instanceof Writable) && !(this instanceof require('./_stream_duplex'))) + return new Writable(options); + + this._writableState = new WritableState(options, this); +diff --git a/test/simple/test-stream-big-push.js b/test/simple/test-stream-big-push.js +index e3787e4..8cd2127 100644 +--- a/test/simple/test-stream-big-push.js ++++ b/test/simple/test-stream-big-push.js +@@ -21,7 +21,7 @@ + + var common = require('../common'); + var assert = require('assert'); +-var stream = require('stream'); ++var stream = require('../../'); + var str = 'asdfasdfasdfasdfasdf'; + + var r = new stream.Readable({ +diff --git a/test/simple/test-stream-end-paused.js b/test/simple/test-stream-end-paused.js +index bb73777..d40efc7 100644 +--- a/test/simple/test-stream-end-paused.js ++++ b/test/simple/test-stream-end-paused.js +@@ -25,7 +25,7 @@ var gotEnd = false; + + // Make sure we don't miss the end event for paused 0-length streams + +-var Readable = require('stream').Readable; ++var Readable = require('../../').Readable; + var stream = new Readable(); + var calledRead = false; + stream._read = function() { +diff --git a/test/simple/test-stream-pipe-after-end.js b/test/simple/test-stream-pipe-after-end.js +index b46ee90..0be8366 100644 +--- a/test/simple/test-stream-pipe-after-end.js ++++ b/test/simple/test-stream-pipe-after-end.js +@@ -22,8 +22,8 @@ + var common = require('../common'); + var assert = require('assert'); + +-var Readable = require('_stream_readable'); +-var Writable = require('_stream_writable'); ++var Readable = require('../../lib/_stream_readable'); ++var Writable = require('../../lib/_stream_writable'); + var util = require('util'); + + util.inherits(TestReadable, Readable); +diff --git a/test/simple/test-stream-pipe-cleanup.js b/test/simple/test-stream-pipe-cleanup.js +deleted file mode 100644 +index f689358..0000000 +--- a/test/simple/test-stream-pipe-cleanup.js ++++ /dev/null +@@ -1,122 +0,0 @@ +-// Copyright Joyent, Inc. and other Node contributors. +-// +-// Permission is hereby granted, free of charge, to any person obtaining a +-// copy of this software and associated documentation files (the +-// "Software"), to deal in the Software without restriction, including +-// without limitation the rights to use, copy, modify, merge, publish, +-// distribute, sublicense, and/or sell copies of the Software, and to permit +-// persons to whom the Software is furnished to do so, subject to the +-// following conditions: +-// +-// The above copyright notice and this permission notice shall be included +-// in all copies or substantial portions of the Software. +-// +-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +-// USE OR OTHER DEALINGS IN THE SOFTWARE. +- +-// This test asserts that Stream.prototype.pipe does not leave listeners +-// hanging on the source or dest. +- +-var common = require('../common'); +-var stream = require('stream'); +-var assert = require('assert'); +-var util = require('util'); +- +-function Writable() { +- this.writable = true; +- this.endCalls = 0; +- stream.Stream.call(this); +-} +-util.inherits(Writable, stream.Stream); +-Writable.prototype.end = function() { +- this.endCalls++; +-}; +- +-Writable.prototype.destroy = function() { +- this.endCalls++; +-}; +- +-function Readable() { +- this.readable = true; +- stream.Stream.call(this); +-} +-util.inherits(Readable, stream.Stream); +- +-function Duplex() { +- this.readable = true; +- Writable.call(this); +-} +-util.inherits(Duplex, Writable); +- +-var i = 0; +-var limit = 100; +- +-var w = new Writable(); +- +-var r; +- +-for (i = 0; i < limit; i++) { +- r = new Readable(); +- r.pipe(w); +- r.emit('end'); +-} +-assert.equal(0, r.listeners('end').length); +-assert.equal(limit, w.endCalls); +- +-w.endCalls = 0; +- +-for (i = 0; i < limit; i++) { +- r = new Readable(); +- r.pipe(w); +- r.emit('close'); +-} +-assert.equal(0, r.listeners('close').length); +-assert.equal(limit, w.endCalls); +- +-w.endCalls = 0; +- +-r = new Readable(); +- +-for (i = 0; i < limit; i++) { +- w = new Writable(); +- r.pipe(w); +- w.emit('close'); +-} +-assert.equal(0, w.listeners('close').length); +- +-r = new Readable(); +-w = new Writable(); +-var d = new Duplex(); +-r.pipe(d); // pipeline A +-d.pipe(w); // pipeline B +-assert.equal(r.listeners('end').length, 2); // A.onend, A.cleanup +-assert.equal(r.listeners('close').length, 2); // A.onclose, A.cleanup +-assert.equal(d.listeners('end').length, 2); // B.onend, B.cleanup +-assert.equal(d.listeners('close').length, 3); // A.cleanup, B.onclose, B.cleanup +-assert.equal(w.listeners('end').length, 0); +-assert.equal(w.listeners('close').length, 1); // B.cleanup +- +-r.emit('end'); +-assert.equal(d.endCalls, 1); +-assert.equal(w.endCalls, 0); +-assert.equal(r.listeners('end').length, 0); +-assert.equal(r.listeners('close').length, 0); +-assert.equal(d.listeners('end').length, 2); // B.onend, B.cleanup +-assert.equal(d.listeners('close').length, 2); // B.onclose, B.cleanup +-assert.equal(w.listeners('end').length, 0); +-assert.equal(w.listeners('close').length, 1); // B.cleanup +- +-d.emit('end'); +-assert.equal(d.endCalls, 1); +-assert.equal(w.endCalls, 1); +-assert.equal(r.listeners('end').length, 0); +-assert.equal(r.listeners('close').length, 0); +-assert.equal(d.listeners('end').length, 0); +-assert.equal(d.listeners('close').length, 0); +-assert.equal(w.listeners('end').length, 0); +-assert.equal(w.listeners('close').length, 0); +diff --git a/test/simple/test-stream-pipe-error-handling.js b/test/simple/test-stream-pipe-error-handling.js +index c5d724b..c7d6b7d 100644 +--- a/test/simple/test-stream-pipe-error-handling.js ++++ b/test/simple/test-stream-pipe-error-handling.js +@@ -21,7 +21,7 @@ + + var common = require('../common'); + var assert = require('assert'); +-var Stream = require('stream').Stream; ++var Stream = require('../../').Stream; + + (function testErrorListenerCatches() { + var source = new Stream(); +diff --git a/test/simple/test-stream-pipe-event.js b/test/simple/test-stream-pipe-event.js +index cb9d5fe..56f8d61 100644 +--- a/test/simple/test-stream-pipe-event.js ++++ b/test/simple/test-stream-pipe-event.js +@@ -20,7 +20,7 @@ + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + var common = require('../common'); +-var stream = require('stream'); ++var stream = require('../../'); + var assert = require('assert'); + var util = require('util'); + +diff --git a/test/simple/test-stream-push-order.js b/test/simple/test-stream-push-order.js +index f2e6ec2..a5c9bf9 100644 +--- a/test/simple/test-stream-push-order.js ++++ b/test/simple/test-stream-push-order.js +@@ -20,7 +20,7 @@ + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + var common = require('../common.js'); +-var Readable = require('stream').Readable; ++var Readable = require('../../').Readable; + var assert = require('assert'); + + var s = new Readable({ +diff --git a/test/simple/test-stream-push-strings.js b/test/simple/test-stream-push-strings.js +index 06f43dc..1701a9a 100644 +--- a/test/simple/test-stream-push-strings.js ++++ b/test/simple/test-stream-push-strings.js +@@ -22,7 +22,7 @@ + var common = require('../common'); + var assert = require('assert'); + +-var Readable = require('stream').Readable; ++var Readable = require('../../').Readable; + var util = require('util'); + + util.inherits(MyStream, Readable); +diff --git a/test/simple/test-stream-readable-event.js b/test/simple/test-stream-readable-event.js +index ba6a577..a8e6f7b 100644 +--- a/test/simple/test-stream-readable-event.js ++++ b/test/simple/test-stream-readable-event.js +@@ -22,7 +22,7 @@ + var common = require('../common'); + var assert = require('assert'); + +-var Readable = require('stream').Readable; ++var Readable = require('../../').Readable; + + (function first() { + // First test, not reading when the readable is added. +diff --git a/test/simple/test-stream-readable-flow-recursion.js b/test/simple/test-stream-readable-flow-recursion.js +index 2891ad6..11689ba 100644 +--- a/test/simple/test-stream-readable-flow-recursion.js ++++ b/test/simple/test-stream-readable-flow-recursion.js +@@ -27,7 +27,7 @@ var assert = require('assert'); + // more data continuously, but without triggering a nextTick + // warning or RangeError. + +-var Readable = require('stream').Readable; ++var Readable = require('../../').Readable; + + // throw an error if we trigger a nextTick warning. + process.throwDeprecation = true; +diff --git a/test/simple/test-stream-unshift-empty-chunk.js b/test/simple/test-stream-unshift-empty-chunk.js +index 0c96476..7827538 100644 +--- a/test/simple/test-stream-unshift-empty-chunk.js ++++ b/test/simple/test-stream-unshift-empty-chunk.js +@@ -24,7 +24,7 @@ var assert = require('assert'); + + // This test verifies that stream.unshift(Buffer(0)) or + // stream.unshift('') does not set state.reading=false. +-var Readable = require('stream').Readable; ++var Readable = require('../../').Readable; + + var r = new Readable(); + var nChunks = 10; +diff --git a/test/simple/test-stream-unshift-read-race.js b/test/simple/test-stream-unshift-read-race.js +index 83fd9fa..17c18aa 100644 +--- a/test/simple/test-stream-unshift-read-race.js ++++ b/test/simple/test-stream-unshift-read-race.js +@@ -29,7 +29,7 @@ var assert = require('assert'); + // 3. push() after the EOF signaling null is an error. + // 4. _read() is not called after pushing the EOF null chunk. + +-var stream = require('stream'); ++var stream = require('../../'); + var hwm = 10; + var r = stream.Readable({ highWaterMark: hwm }); + var chunks = 10; +@@ -51,7 +51,14 @@ r._read = function(n) { + + function push(fast) { + assert(!pushedNull, 'push() after null push'); +- var c = pos >= data.length ? null : data.slice(pos, pos + n); ++ var c; ++ if (pos >= data.length) ++ c = null; ++ else { ++ if (n + pos > data.length) ++ n = data.length - pos; ++ c = data.slice(pos, pos + n); ++ } + pushedNull = c === null; + if (fast) { + pos += n; +diff --git a/test/simple/test-stream-writev.js b/test/simple/test-stream-writev.js +index 5b49e6e..b5321f3 100644 +--- a/test/simple/test-stream-writev.js ++++ b/test/simple/test-stream-writev.js +@@ -22,7 +22,7 @@ + var common = require('../common'); + var assert = require('assert'); + +-var stream = require('stream'); ++var stream = require('../../'); + + var queue = []; + for (var decode = 0; decode < 2; decode++) { +diff --git a/test/simple/test-stream2-basic.js b/test/simple/test-stream2-basic.js +index 3814bf0..248c1be 100644 +--- a/test/simple/test-stream2-basic.js ++++ b/test/simple/test-stream2-basic.js +@@ -21,7 +21,7 @@ + + + var common = require('../common.js'); +-var R = require('_stream_readable'); ++var R = require('../../lib/_stream_readable'); + var assert = require('assert'); + + var util = require('util'); +diff --git a/test/simple/test-stream2-compatibility.js b/test/simple/test-stream2-compatibility.js +index 6cdd4e9..f0fa84b 100644 +--- a/test/simple/test-stream2-compatibility.js ++++ b/test/simple/test-stream2-compatibility.js +@@ -21,7 +21,7 @@ + + + var common = require('../common.js'); +-var R = require('_stream_readable'); ++var R = require('../../lib/_stream_readable'); + var assert = require('assert'); + + var util = require('util'); +diff --git a/test/simple/test-stream2-finish-pipe.js b/test/simple/test-stream2-finish-pipe.js +index 39b274f..006a19b 100644 +--- a/test/simple/test-stream2-finish-pipe.js ++++ b/test/simple/test-stream2-finish-pipe.js +@@ -20,7 +20,7 @@ + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + var common = require('../common.js'); +-var stream = require('stream'); ++var stream = require('../../'); + var Buffer = require('buffer').Buffer; + + var r = new stream.Readable(); +diff --git a/test/simple/test-stream2-fs.js b/test/simple/test-stream2-fs.js +deleted file mode 100644 +index e162406..0000000 +--- a/test/simple/test-stream2-fs.js ++++ /dev/null +@@ -1,72 +0,0 @@ +-// Copyright Joyent, Inc. and other Node contributors. +-// +-// Permission is hereby granted, free of charge, to any person obtaining a +-// copy of this software and associated documentation files (the +-// "Software"), to deal in the Software without restriction, including +-// without limitation the rights to use, copy, modify, merge, publish, +-// distribute, sublicense, and/or sell copies of the Software, and to permit +-// persons to whom the Software is furnished to do so, subject to the +-// following conditions: +-// +-// The above copyright notice and this permission notice shall be included +-// in all copies or substantial portions of the Software. +-// +-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +-// USE OR OTHER DEALINGS IN THE SOFTWARE. +- +- +-var common = require('../common.js'); +-var R = require('_stream_readable'); +-var assert = require('assert'); +- +-var fs = require('fs'); +-var FSReadable = fs.ReadStream; +- +-var path = require('path'); +-var file = path.resolve(common.fixturesDir, 'x1024.txt'); +- +-var size = fs.statSync(file).size; +- +-var expectLengths = [1024]; +- +-var util = require('util'); +-var Stream = require('stream'); +- +-util.inherits(TestWriter, Stream); +- +-function TestWriter() { +- Stream.apply(this); +- this.buffer = []; +- this.length = 0; +-} +- +-TestWriter.prototype.write = function(c) { +- this.buffer.push(c.toString()); +- this.length += c.length; +- return true; +-}; +- +-TestWriter.prototype.end = function(c) { +- if (c) this.buffer.push(c.toString()); +- this.emit('results', this.buffer); +-} +- +-var r = new FSReadable(file); +-var w = new TestWriter(); +- +-w.on('results', function(res) { +- console.error(res, w.length); +- assert.equal(w.length, size); +- var l = 0; +- assert.deepEqual(res.map(function (c) { +- return c.length; +- }), expectLengths); +- console.log('ok'); +-}); +- +-r.pipe(w); +diff --git a/test/simple/test-stream2-httpclient-response-end.js b/test/simple/test-stream2-httpclient-response-end.js +deleted file mode 100644 +index 15cffc2..0000000 +--- a/test/simple/test-stream2-httpclient-response-end.js ++++ /dev/null +@@ -1,52 +0,0 @@ +-// Copyright Joyent, Inc. and other Node contributors. +-// +-// Permission is hereby granted, free of charge, to any person obtaining a +-// copy of this software and associated documentation files (the +-// "Software"), to deal in the Software without restriction, including +-// without limitation the rights to use, copy, modify, merge, publish, +-// distribute, sublicense, and/or sell copies of the Software, and to permit +-// persons to whom the Software is furnished to do so, subject to the +-// following conditions: +-// +-// The above copyright notice and this permission notice shall be included +-// in all copies or substantial portions of the Software. +-// +-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +-// USE OR OTHER DEALINGS IN THE SOFTWARE. +- +-var common = require('../common.js'); +-var assert = require('assert'); +-var http = require('http'); +-var msg = 'Hello'; +-var readable_event = false; +-var end_event = false; +-var server = http.createServer(function(req, res) { +- res.writeHead(200, {'Content-Type': 'text/plain'}); +- res.end(msg); +-}).listen(common.PORT, function() { +- http.get({port: common.PORT}, function(res) { +- var data = ''; +- res.on('readable', function() { +- console.log('readable event'); +- readable_event = true; +- data += res.read(); +- }); +- res.on('end', function() { +- console.log('end event'); +- end_event = true; +- assert.strictEqual(msg, data); +- server.close(); +- }); +- }); +-}); +- +-process.on('exit', function() { +- assert(readable_event); +- assert(end_event); +-}); +- +diff --git a/test/simple/test-stream2-large-read-stall.js b/test/simple/test-stream2-large-read-stall.js +index 2fbfbca..667985b 100644 +--- a/test/simple/test-stream2-large-read-stall.js ++++ b/test/simple/test-stream2-large-read-stall.js +@@ -30,7 +30,7 @@ var PUSHSIZE = 20; + var PUSHCOUNT = 1000; + var HWM = 50; + +-var Readable = require('stream').Readable; ++var Readable = require('../../').Readable; + var r = new Readable({ + highWaterMark: HWM + }); +@@ -39,23 +39,23 @@ var rs = r._readableState; + r._read = push; + + r.on('readable', function() { +- console.error('>> readable'); ++ //console.error('>> readable'); + do { +- console.error(' > read(%d)', READSIZE); ++ //console.error(' > read(%d)', READSIZE); + var ret = r.read(READSIZE); +- console.error(' < %j (%d remain)', ret && ret.length, rs.length); ++ //console.error(' < %j (%d remain)', ret && ret.length, rs.length); + } while (ret && ret.length === READSIZE); + +- console.error('<< after read()', +- ret && ret.length, +- rs.needReadable, +- rs.length); ++ //console.error('<< after read()', ++ // ret && ret.length, ++ // rs.needReadable, ++ // rs.length); + }); + + var endEmitted = false; + r.on('end', function() { + endEmitted = true; +- console.error('end'); ++ //console.error('end'); + }); + + var pushes = 0; +@@ -64,11 +64,11 @@ function push() { + return; + + if (pushes++ === PUSHCOUNT) { +- console.error(' push(EOF)'); ++ //console.error(' push(EOF)'); + return r.push(null); + } + +- console.error(' push #%d', pushes); ++ //console.error(' push #%d', pushes); + if (r.push(new Buffer(PUSHSIZE))) + setTimeout(push); + } +diff --git a/test/simple/test-stream2-objects.js b/test/simple/test-stream2-objects.js +index 3e6931d..ff47d89 100644 +--- a/test/simple/test-stream2-objects.js ++++ b/test/simple/test-stream2-objects.js +@@ -21,8 +21,8 @@ + + + var common = require('../common.js'); +-var Readable = require('_stream_readable'); +-var Writable = require('_stream_writable'); ++var Readable = require('../../lib/_stream_readable'); ++var Writable = require('../../lib/_stream_writable'); + var assert = require('assert'); + + // tiny node-tap lookalike. +diff --git a/test/simple/test-stream2-pipe-error-handling.js b/test/simple/test-stream2-pipe-error-handling.js +index cf7531c..e3f3e4e 100644 +--- a/test/simple/test-stream2-pipe-error-handling.js ++++ b/test/simple/test-stream2-pipe-error-handling.js +@@ -21,7 +21,7 @@ + + var common = require('../common'); + var assert = require('assert'); +-var stream = require('stream'); ++var stream = require('../../'); + + (function testErrorListenerCatches() { + var count = 1000; +diff --git a/test/simple/test-stream2-pipe-error-once-listener.js b/test/simple/test-stream2-pipe-error-once-listener.js +index 5e8e3cb..53b2616 100755 +--- a/test/simple/test-stream2-pipe-error-once-listener.js ++++ b/test/simple/test-stream2-pipe-error-once-listener.js +@@ -24,7 +24,7 @@ var common = require('../common.js'); + var assert = require('assert'); + + var util = require('util'); +-var stream = require('stream'); ++var stream = require('../../'); + + + var Read = function() { +diff --git a/test/simple/test-stream2-push.js b/test/simple/test-stream2-push.js +index b63edc3..eb2b0e9 100644 +--- a/test/simple/test-stream2-push.js ++++ b/test/simple/test-stream2-push.js +@@ -20,7 +20,7 @@ + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + var common = require('../common.js'); +-var stream = require('stream'); ++var stream = require('../../'); + var Readable = stream.Readable; + var Writable = stream.Writable; + var assert = require('assert'); +diff --git a/test/simple/test-stream2-read-sync-stack.js b/test/simple/test-stream2-read-sync-stack.js +index e8a7305..9740a47 100644 +--- a/test/simple/test-stream2-read-sync-stack.js ++++ b/test/simple/test-stream2-read-sync-stack.js +@@ -21,7 +21,7 @@ + + var common = require('../common'); + var assert = require('assert'); +-var Readable = require('stream').Readable; ++var Readable = require('../../').Readable; + var r = new Readable(); + var N = 256 * 1024; + +diff --git a/test/simple/test-stream2-readable-empty-buffer-no-eof.js b/test/simple/test-stream2-readable-empty-buffer-no-eof.js +index cd30178..4b1659d 100644 +--- a/test/simple/test-stream2-readable-empty-buffer-no-eof.js ++++ b/test/simple/test-stream2-readable-empty-buffer-no-eof.js +@@ -22,10 +22,9 @@ + var common = require('../common'); + var assert = require('assert'); + +-var Readable = require('stream').Readable; ++var Readable = require('../../').Readable; + + test1(); +-test2(); + + function test1() { + var r = new Readable(); +@@ -88,31 +87,3 @@ function test1() { + console.log('ok'); + }); + } +- +-function test2() { +- var r = new Readable({ encoding: 'base64' }); +- var reads = 5; +- r._read = function(n) { +- if (!reads--) +- return r.push(null); // EOF +- else +- return r.push(new Buffer('x')); +- }; +- +- var results = []; +- function flow() { +- var chunk; +- while (null !== (chunk = r.read())) +- results.push(chunk + ''); +- } +- r.on('readable', flow); +- r.on('end', function() { +- results.push('EOF'); +- }); +- flow(); +- +- process.on('exit', function() { +- assert.deepEqual(results, [ 'eHh4', 'eHg=', 'EOF' ]); +- console.log('ok'); +- }); +-} +diff --git a/test/simple/test-stream2-readable-from-list.js b/test/simple/test-stream2-readable-from-list.js +index 7c96ffe..04a96f5 100644 +--- a/test/simple/test-stream2-readable-from-list.js ++++ b/test/simple/test-stream2-readable-from-list.js +@@ -21,7 +21,7 @@ + + var assert = require('assert'); + var common = require('../common.js'); +-var fromList = require('_stream_readable')._fromList; ++var fromList = require('../../lib/_stream_readable')._fromList; + + // tiny node-tap lookalike. + var tests = []; +diff --git a/test/simple/test-stream2-readable-legacy-drain.js b/test/simple/test-stream2-readable-legacy-drain.js +index 675da8e..51fd3d5 100644 +--- a/test/simple/test-stream2-readable-legacy-drain.js ++++ b/test/simple/test-stream2-readable-legacy-drain.js +@@ -22,7 +22,7 @@ + var common = require('../common'); + var assert = require('assert'); + +-var Stream = require('stream'); ++var Stream = require('../../'); + var Readable = Stream.Readable; + + var r = new Readable(); +diff --git a/test/simple/test-stream2-readable-non-empty-end.js b/test/simple/test-stream2-readable-non-empty-end.js +index 7314ae7..c971898 100644 +--- a/test/simple/test-stream2-readable-non-empty-end.js ++++ b/test/simple/test-stream2-readable-non-empty-end.js +@@ -21,7 +21,7 @@ + + var assert = require('assert'); + var common = require('../common.js'); +-var Readable = require('_stream_readable'); ++var Readable = require('../../lib/_stream_readable'); + + var len = 0; + var chunks = new Array(10); +diff --git a/test/simple/test-stream2-readable-wrap-empty.js b/test/simple/test-stream2-readable-wrap-empty.js +index 2e5cf25..fd8a3dc 100644 +--- a/test/simple/test-stream2-readable-wrap-empty.js ++++ b/test/simple/test-stream2-readable-wrap-empty.js +@@ -22,7 +22,7 @@ + var common = require('../common'); + var assert = require('assert'); + +-var Readable = require('_stream_readable'); ++var Readable = require('../../lib/_stream_readable'); + var EE = require('events').EventEmitter; + + var oldStream = new EE(); +diff --git a/test/simple/test-stream2-readable-wrap.js b/test/simple/test-stream2-readable-wrap.js +index 90eea01..6b177f7 100644 +--- a/test/simple/test-stream2-readable-wrap.js ++++ b/test/simple/test-stream2-readable-wrap.js +@@ -22,8 +22,8 @@ + var common = require('../common'); + var assert = require('assert'); + +-var Readable = require('_stream_readable'); +-var Writable = require('_stream_writable'); ++var Readable = require('../../lib/_stream_readable'); ++var Writable = require('../../lib/_stream_writable'); + var EE = require('events').EventEmitter; + + var testRuns = 0, completedRuns = 0; +diff --git a/test/simple/test-stream2-set-encoding.js b/test/simple/test-stream2-set-encoding.js +index 5d2c32a..685531b 100644 +--- a/test/simple/test-stream2-set-encoding.js ++++ b/test/simple/test-stream2-set-encoding.js +@@ -22,7 +22,7 @@ + + var common = require('../common.js'); + var assert = require('assert'); +-var R = require('_stream_readable'); ++var R = require('../../lib/_stream_readable'); + var util = require('util'); + + // tiny node-tap lookalike. +diff --git a/test/simple/test-stream2-transform.js b/test/simple/test-stream2-transform.js +index 9c9ddd8..a0cacc6 100644 +--- a/test/simple/test-stream2-transform.js ++++ b/test/simple/test-stream2-transform.js +@@ -21,8 +21,8 @@ + + var assert = require('assert'); + var common = require('../common.js'); +-var PassThrough = require('_stream_passthrough'); +-var Transform = require('_stream_transform'); ++var PassThrough = require('../../').PassThrough; ++var Transform = require('../../').Transform; + + // tiny node-tap lookalike. + var tests = []; +diff --git a/test/simple/test-stream2-unpipe-drain.js b/test/simple/test-stream2-unpipe-drain.js +index d66dc3c..365b327 100644 +--- a/test/simple/test-stream2-unpipe-drain.js ++++ b/test/simple/test-stream2-unpipe-drain.js +@@ -22,7 +22,7 @@ + + var common = require('../common.js'); + var assert = require('assert'); +-var stream = require('stream'); ++var stream = require('../../'); + var crypto = require('crypto'); + + var util = require('util'); +diff --git a/test/simple/test-stream2-unpipe-leak.js b/test/simple/test-stream2-unpipe-leak.js +index 99f8746..17c92ae 100644 +--- a/test/simple/test-stream2-unpipe-leak.js ++++ b/test/simple/test-stream2-unpipe-leak.js +@@ -22,7 +22,7 @@ + + var common = require('../common.js'); + var assert = require('assert'); +-var stream = require('stream'); ++var stream = require('../../'); + + var chunk = new Buffer('hallo'); + +diff --git a/test/simple/test-stream2-writable.js b/test/simple/test-stream2-writable.js +index 704100c..209c3a6 100644 +--- a/test/simple/test-stream2-writable.js ++++ b/test/simple/test-stream2-writable.js +@@ -20,8 +20,8 @@ + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + var common = require('../common.js'); +-var W = require('_stream_writable'); +-var D = require('_stream_duplex'); ++var W = require('../../').Writable; ++var D = require('../../').Duplex; + var assert = require('assert'); + + var util = require('util'); +diff --git a/test/simple/test-stream3-pause-then-read.js b/test/simple/test-stream3-pause-then-read.js +index b91bde3..2f72c15 100644 +--- a/test/simple/test-stream3-pause-then-read.js ++++ b/test/simple/test-stream3-pause-then-read.js +@@ -22,7 +22,7 @@ + var common = require('../common'); + var assert = require('assert'); + +-var stream = require('stream'); ++var stream = require('../../'); + var Readable = stream.Readable; + var Writable = stream.Writable; +
@@ -0,0 +1,89 @@
+// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +module.exports = Duplex; + +/*<replacement>*/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; +} +/*</replacement>*/ + + +/*<replacement>*/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/*</replacement>*/ + +var Readable = require('./_stream_readable'); +var Writable = require('./_stream_writable'); + +util.inherits(Duplex, Readable); + +forEach(objectKeys(Writable.prototype), function(method) { + if (!Duplex.prototype[method]) + Duplex.prototype[method] = Writable.prototype[method]; +}); + +function Duplex(options) { + if (!(this instanceof Duplex)) + return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) + this.readable = false; + + if (options && options.writable === false) + this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) + this.allowHalfOpen = false; + + this.once('end', onend); +} + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) + return; + + // no more data can be written. + // But allow more writes to happen in this tick. + process.nextTick(this.end.bind(this)); +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +}
@@ -0,0 +1,46 @@
+// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +module.exports = PassThrough; + +var Transform = require('./_stream_transform'); + +/*<replacement>*/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/*</replacement>*/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) + return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function(chunk, encoding, cb) { + cb(null, chunk); +};
@@ -0,0 +1,951 @@
+// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +module.exports = Readable; + +/*<replacement>*/ +var isArray = require('isarray'); +/*</replacement>*/ + + +/*<replacement>*/ +var Buffer = require('buffer').Buffer; +/*</replacement>*/ + +Readable.ReadableState = ReadableState; + +var EE = require('events').EventEmitter; + +/*<replacement>*/ +if (!EE.listenerCount) EE.listenerCount = function(emitter, type) { + return emitter.listeners(type).length; +}; +/*</replacement>*/ + +var Stream = require('stream'); + +/*<replacement>*/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/*</replacement>*/ + +var StringDecoder; + + +/*<replacement>*/ +var debug = require('util'); +if (debug && debug.debuglog) { + debug = debug.debuglog('stream'); +} else { + debug = function () {}; +} +/*</replacement>*/ + + +util.inherits(Readable, Stream); + +function ReadableState(options, stream) { + var Duplex = require('./_stream_duplex'); + + options = options || {}; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + var defaultHwm = options.objectMode ? 16 : 16 * 1024; + this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.buffer = []; + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + if (stream instanceof Duplex) + this.objectMode = this.objectMode || !!options.readableObjectMode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // when piping, we only care about 'readable' events that happen + // after read()ing all the bytes and not getting any pushback. + this.ranOut = false; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) + StringDecoder = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + var Duplex = require('./_stream_duplex'); + + if (!(this instanceof Readable)) + return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + Stream.call(this); +} + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function(chunk, encoding) { + var state = this._readableState; + + if (util.isString(chunk) && !state.objectMode) { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = new Buffer(chunk, encoding); + encoding = ''; + } + } + + return readableAddChunk(this, state, chunk, encoding, false); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function(chunk) { + var state = this._readableState; + return readableAddChunk(this, state, chunk, '', true); +}; + +function readableAddChunk(stream, state, chunk, encoding, addToFront) { + var er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (util.isNullOrUndefined(chunk)) { + state.reading = false; + if (!state.ended) + onEofChunk(stream, state); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (state.ended && !addToFront) { + var e = new Error('stream.push() after EOF'); + stream.emit('error', e); + } else if (state.endEmitted && addToFront) { + var e = new Error('stream.unshift() after end event'); + stream.emit('error', e); + } else { + if (state.decoder && !addToFront && !encoding) + chunk = state.decoder.write(chunk); + + if (!addToFront) + state.reading = false; + + // if we want the data now, just emit it. + if (state.flowing && state.length === 0 && !state.sync) { + stream.emit('data', chunk); + stream.read(0); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) + state.buffer.unshift(chunk); + else + state.buffer.push(chunk); + + if (state.needReadable) + emitReadable(stream); + } + + maybeReadMore(stream, state); + } + } else if (!addToFront) { + state.reading = false; + } + + return needMoreData(state); +} + + + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && + (state.needReadable || + state.length < state.highWaterMark || + state.length === 0); +} + +// backwards compatibility. +Readable.prototype.setEncoding = function(enc) { + if (!StringDecoder) + StringDecoder = require('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; + return this; +}; + +// Don't raise the hwm > 128MB +var MAX_HWM = 0x800000; +function roundUpToNextPowerOf2(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 + n--; + for (var p = 1; p < 32; p <<= 1) n |= n >> p; + n++; + } + return n; +} + +function howMuchToRead(n, state) { + if (state.length === 0 && state.ended) + return 0; + + if (state.objectMode) + return n === 0 ? 0 : 1; + + if (isNaN(n) || util.isNull(n)) { + // only flow one buffer at a time + if (state.flowing && state.buffer.length) + return state.buffer[0].length; + else + return state.length; + } + + if (n <= 0) + return 0; + + // If we're asking for more than the target buffer level, + // then raise the water mark. Bump up to the next highest + // power of 2, to prevent increasing it excessively in tiny + // amounts. + if (n > state.highWaterMark) + state.highWaterMark = roundUpToNextPowerOf2(n); + + // don't have that much. return null, unless we've ended. + if (n > state.length) { + if (!state.ended) { + state.needReadable = true; + return 0; + } else + return state.length; + } + + return n; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function(n) { + debug('read', n); + var state = this._readableState; + var nOrig = n; + + if (!util.isNumber(n) || n > 0) + state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && + state.needReadable && + (state.length >= state.highWaterMark || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) + endReadable(this); + else + emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) + endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + debug('need readable', doRead); + + // if we currently have less than the highWaterMark, then also read some + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } + + if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) + state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + } + + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (doRead && !state.reading) + n = howMuchToRead(nOrig, state); + + var ret; + if (n > 0) + ret = fromList(n, state); + else + ret = null; + + if (util.isNull(ret)) { + state.needReadable = true; + n = 0; + } + + state.length -= n; + + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (state.length === 0 && !state.ended) + state.needReadable = true; + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended && state.length === 0) + endReadable(this); + + if (!util.isNull(ret)) + this.emit('data', ret); + + return ret; +}; + +function chunkInvalid(state, chunk) { + var er = null; + if (!util.isBuffer(chunk) && + !util.isString(chunk) && + !util.isNullOrUndefined(chunk) && + !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + + +function onEofChunk(stream, state) { + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // emit 'readable' now to make sure it gets picked up. + emitReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + if (state.sync) + process.nextTick(function() { + emitReadable_(stream); + }); + else + emitReadable_(stream); + } +} + +function emitReadable_(stream) { + debug('emit readable'); + stream.emit('readable'); + flow(stream); +} + + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + process.nextTick(function() { + maybeReadMore_(stream, state); + }); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && + state.length < state.highWaterMark) { + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break; + else + len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function(n) { + this.emit('error', new Error('not implemented')); +}; + +Readable.prototype.pipe = function(dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && + dest !== process.stdout && + dest !== process.stderr; + + var endFn = doEnd ? onend : cleanup; + if (state.endEmitted) + process.nextTick(endFn); + else + src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable) { + debug('onunpipe'); + if (readable === src) { + cleanup(); + } + } + + function onend() { + debug('onend'); + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + function cleanup() { + debug('cleanup'); + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', cleanup); + src.removeListener('data', ondata); + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (state.awaitDrain && + (!dest._writableState || dest._writableState.needDrain)) + ondrain(); + } + + src.on('data', ondata); + function ondata(chunk) { + debug('ondata'); + var ret = dest.write(chunk); + if (false === ret) { + debug('false write response, pause', + src._readableState.awaitDrain); + src._readableState.awaitDrain++; + src.pause(); + } + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EE.listenerCount(dest, 'error') === 0) + dest.emit('error', er); + } + // This is a brutally ugly hack to make sure that our error handler + // is attached before any userland ones. NEVER DO THIS. + if (!dest._events || !dest._events.error) + dest.on('error', onerror); + else if (isArray(dest._events.error)) + dest._events.error.unshift(onerror); + else + dest._events.error = [onerror, dest._events.error]; + + + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + debug('pipe resume'); + src.resume(); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function() { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) + state.awaitDrain--; + if (state.awaitDrain === 0 && EE.listenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} + + +Readable.prototype.unpipe = function(dest) { + var state = this._readableState; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) + return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) + return this; + + if (!dest) + dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) + dest.emit('unpipe', this); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + + for (var i = 0; i < len; i++) + dests[i].emit('unpipe', this); + return this; + } + + // try to find the right one. + var i = indexOf(state.pipes, dest); + if (i === -1) + return this; + + state.pipes.splice(i, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) + state.pipes = state.pipes[0]; + + dest.emit('unpipe', this); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function(ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + // If listening to data, and it has not explicitly been paused, + // then call resume to start the flow of data on the next tick. + if (ev === 'data' && false !== this._readableState.flowing) { + this.resume(); + } + + if (ev === 'readable' && this.readable) { + var state = this._readableState; + if (!state.readableListening) { + state.readableListening = true; + state.emittedReadable = false; + state.needReadable = true; + if (!state.reading) { + var self = this; + process.nextTick(function() { + debug('readable nexttick read 0'); + self.read(0); + }); + } else if (state.length) { + emitReadable(this, state); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function() { + var state = this._readableState; + if (!state.flowing) { + debug('resume'); + state.flowing = true; + if (!state.reading) { + debug('resume read 0'); + this.read(0); + } + resume(this, state); + } + return this; +}; + +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + process.nextTick(function() { + resume_(stream, state); + }); + } +} + +function resume_(stream, state) { + state.resumeScheduled = false; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) + stream.read(0); +} + +Readable.prototype.pause = function() { + debug('call pause flowing=%j', this._readableState.flowing); + if (false !== this._readableState.flowing) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + return this; +}; + +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + if (state.flowing) { + do { + var chunk = stream.read(); + } while (null !== chunk && state.flowing); + } +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function(stream) { + var state = this._readableState; + var paused = false; + + var self = this; + stream.on('end', function() { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) + self.push(chunk); + } + + self.push(null); + }); + + stream.on('data', function(chunk) { + debug('wrapped data'); + if (state.decoder) + chunk = state.decoder.write(chunk); + if (!chunk || !state.objectMode && !chunk.length) + return; + + var ret = self.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (util.isFunction(stream[i]) && util.isUndefined(this[i])) { + this[i] = function(method) { return function() { + return stream[method].apply(stream, arguments); + }}(i); + } + } + + // proxy certain important events. + var events = ['error', 'close', 'destroy', 'pause', 'resume']; + forEach(events, function(ev) { + stream.on(ev, self.emit.bind(self, ev)); + }); + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + self._read = function(n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + + return self; +}; + + + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +function fromList(n, state) { + var list = state.buffer; + var length = state.length; + var stringMode = !!state.decoder; + var objectMode = !!state.objectMode; + var ret; + + // nothing in the list, definitely empty. + if (list.length === 0) + return null; + + if (length === 0) + ret = null; + else if (objectMode) + ret = list.shift(); + else if (!n || n >= length) { + // read it all, truncate the array. + if (stringMode) + ret = list.join(''); + else + ret = Buffer.concat(list, length); + list.length = 0; + } else { + // read just some of it. + if (n < list[0].length) { + // just take a part of the first list item. + // slice is the same for buffers and strings. + var buf = list[0]; + ret = buf.slice(0, n); + list[0] = buf.slice(n); + } else if (n === list[0].length) { + // first list is a perfect match + ret = list.shift(); + } else { + // complex case. + // we have enough to cover it, but it spans past the first buffer. + if (stringMode) + ret = ''; + else + ret = new Buffer(n); + + var c = 0; + for (var i = 0, l = list.length; i < l && c < n; i++) { + var buf = list[0]; + var cpy = Math.min(n - c, buf.length); + + if (stringMode) + ret += buf.slice(0, cpy); + else + buf.copy(ret, c, 0, cpy); + + if (cpy < buf.length) + list[0] = buf.slice(cpy); + else + list.shift(); + + c += cpy; + } + } + } + + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) + throw new Error('endReadable called on non-empty stream'); + + if (!state.endEmitted) { + state.ended = true; + process.nextTick(function() { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } + }); + } +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} + +function indexOf (xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +}
@@ -0,0 +1,209 @@
+// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +module.exports = Transform; + +var Duplex = require('./_stream_duplex'); + +/*<replacement>*/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/*</replacement>*/ + +util.inherits(Transform, Duplex); + + +function TransformState(options, stream) { + this.afterTransform = function(er, data) { + return afterTransform(stream, er, data); + }; + + this.needTransform = false; + this.transforming = false; + this.writecb = null; + this.writechunk = null; +} + +function afterTransform(stream, er, data) { + var ts = stream._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) + return stream.emit('error', new Error('no writecb in Transform class')); + + ts.writechunk = null; + ts.writecb = null; + + if (!util.isNullOrUndefined(data)) + stream.push(data); + + if (cb) + cb(er); + + var rs = stream._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + stream._read(rs.highWaterMark); + } +} + + +function Transform(options) { + if (!(this instanceof Transform)) + return new Transform(options); + + Duplex.call(this, options); + + this._transformState = new TransformState(options, this); + + // when the writable side finishes, then flush out anything remaining. + var stream = this; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + this.once('prefinish', function() { + if (util.isFunction(this._flush)) + this._flush(function(er) { + done(stream, er); + }); + else + done(stream); + }); +} + +Transform.prototype.push = function(chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function(chunk, encoding, cb) { + throw new Error('not implemented'); +}; + +Transform.prototype._write = function(chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || + rs.needReadable || + rs.length < rs.highWaterMark) + this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function(n) { + var ts = this._transformState; + + if (!util.isNull(ts.writechunk) && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + + +function done(stream, er) { + if (er) + return stream.emit('error', er); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + var ws = stream._writableState; + var ts = stream._transformState; + + if (ws.length) + throw new Error('calling transform done when ws.length != 0'); + + if (ts.transforming) + throw new Error('calling transform done when still transforming'); + + return stream.push(null); +}
@@ -0,0 +1,477 @@
+// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, cb), and it'll handle all +// the drain event emission and buffering. + +module.exports = Writable; + +/*<replacement>*/ +var Buffer = require('buffer').Buffer; +/*</replacement>*/ + +Writable.WritableState = WritableState; + + +/*<replacement>*/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/*</replacement>*/ + +var Stream = require('stream'); + +util.inherits(Writable, Stream); + +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; +} + +function WritableState(options, stream) { + var Duplex = require('./_stream_duplex'); + + options = options || {}; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + var defaultHwm = options.objectMode ? 16 : 16 * 1024; + this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + if (stream instanceof Duplex) + this.objectMode = this.objectMode || !!options.writableObjectMode; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // when true all writes will be buffered until .uncork() call + this.corked = 0; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function(er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.buffer = []; + + // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted + this.pendingcb = 0; + + // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; +} + +function Writable(options) { + var Duplex = require('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, though they're not + // instanceof Writable, they're instanceof Readable. + if (!(this instanceof Writable) && !(this instanceof Duplex)) + return new Writable(options); + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function() { + this.emit('error', new Error('Cannot pipe. Not readable.')); +}; + + +function writeAfterEnd(stream, state, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); +} + +// If we get something that is not a buffer, string, null, or undefined, +// and we're not in objectMode, then that's an error. +// Otherwise stream chunks are all considered to be of length=1, and the +// watermarks determine how many objects to keep in the buffer, rather than +// how many bytes or characters. +function validChunk(stream, state, chunk, cb) { + var valid = true; + if (!util.isBuffer(chunk) && + !util.isString(chunk) && + !util.isNullOrUndefined(chunk) && + !state.objectMode) { + var er = new TypeError('Invalid non-string/buffer chunk'); + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); + valid = false; + } + return valid; +} + +Writable.prototype.write = function(chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + + if (util.isFunction(encoding)) { + cb = encoding; + encoding = null; + } + + if (util.isBuffer(chunk)) + encoding = 'buffer'; + else if (!encoding) + encoding = state.defaultEncoding; + + if (!util.isFunction(cb)) + cb = function() {}; + + if (state.ended) + writeAfterEnd(this, state, cb); + else if (validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, chunk, encoding, cb); + } + + return ret; +}; + +Writable.prototype.cork = function() { + var state = this._writableState; + + state.corked++; +}; + +Writable.prototype.uncork = function() { + var state = this._writableState; + + if (state.corked) { + state.corked--; + + if (!state.writing && + !state.corked && + !state.finished && + !state.bufferProcessing && + state.buffer.length) + clearBuffer(this, state); + } +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && + state.decodeStrings !== false && + util.isString(chunk)) { + chunk = new Buffer(chunk, encoding); + } + return chunk; +} + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, chunk, encoding, cb) { + chunk = decodeChunk(state, chunk, encoding); + if (util.isBuffer(chunk)) + encoding = 'buffer'; + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) + state.needDrain = true; + + if (state.writing || state.corked) + state.buffer.push(new WriteReq(chunk, encoding, cb)); + else + doWrite(stream, state, false, len, chunk, encoding, cb); + + return ret; +} + +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (writev) + stream._writev(chunk, state.onwrite); + else + stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + if (sync) + process.nextTick(function() { + state.pendingcb--; + cb(er); + }); + else { + state.pendingcb--; + cb(er); + } + + stream._writableState.errorEmitted = true; + stream.emit('error', er); +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) + onwriteError(stream, state, sync, er, cb); + else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(stream, state); + + if (!finished && + !state.corked && + !state.bufferProcessing && + state.buffer.length) { + clearBuffer(stream, state); + } + + if (sync) { + process.nextTick(function() { + afterWrite(stream, state, finished, cb); + }); + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) + onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + + if (stream._writev && state.buffer.length > 1) { + // Fast case, write everything using _writev() + var cbs = []; + for (var c = 0; c < state.buffer.length; c++) + cbs.push(state.buffer[c].callback); + + // count the one we are adding, as well. + // TODO(isaacs) clean this up + state.pendingcb++; + doWrite(stream, state, true, state.length, state.buffer, '', function(err) { + for (var i = 0; i < cbs.length; i++) { + state.pendingcb--; + cbs[i](err); + } + }); + + // Clear buffer + state.buffer = []; + } else { + // Slow case, write chunks one-by-one + for (var c = 0; c < state.buffer.length; c++) { + var entry = state.buffer[c]; + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, false, len, chunk, encoding, cb); + + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + c++; + break; + } + } + + if (c < state.buffer.length) + state.buffer = state.buffer.slice(c); + else + state.buffer.length = 0; + } + + state.bufferProcessing = false; +} + +Writable.prototype._write = function(chunk, encoding, cb) { + cb(new Error('not implemented')); + +}; + +Writable.prototype._writev = null; + +Writable.prototype.end = function(chunk, encoding, cb) { + var state = this._writableState; + + if (util.isFunction(chunk)) { + cb = chunk; + chunk = null; + encoding = null; + } else if (util.isFunction(encoding)) { + cb = encoding; + encoding = null; + } + + if (!util.isNullOrUndefined(chunk)) + this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) + endWritable(this, state, cb); +}; + + +function needFinish(stream, state) { + return (state.ending && + state.length === 0 && + !state.finished && + !state.writing); +} + +function prefinish(stream, state) { + if (!state.prefinished) { + state.prefinished = true; + stream.emit('prefinish'); + } +} + +function finishMaybe(stream, state) { + var need = needFinish(stream, state); + if (need) { + if (state.pendingcb === 0) { + prefinish(stream, state); + state.finished = true; + stream.emit('finish'); + } else + prefinish(stream, state); + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) + process.nextTick(cb); + else + stream.once('finish', cb); + } + state.ended = true; +}
@@ -0,0 +1,19 @@
+Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE.
@@ -0,0 +1,3 @@
+# core-util-is + +The `util.is*` functions introduced in Node v0.12.
@@ -0,0 +1,604 @@
+diff --git a/lib/util.js b/lib/util.js +index a03e874..9074e8e 100644 +--- a/lib/util.js ++++ b/lib/util.js +@@ -19,430 +19,6 @@ + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + +-var formatRegExp = /%[sdj%]/g; +-exports.format = function(f) { +- if (!isString(f)) { +- var objects = []; +- for (var i = 0; i < arguments.length; i++) { +- objects.push(inspect(arguments[i])); +- } +- return objects.join(' '); +- } +- +- var i = 1; +- var args = arguments; +- var len = args.length; +- var str = String(f).replace(formatRegExp, function(x) { +- if (x === '%%') return '%'; +- if (i >= len) return x; +- switch (x) { +- case '%s': return String(args[i++]); +- case '%d': return Number(args[i++]); +- case '%j': +- try { +- return JSON.stringify(args[i++]); +- } catch (_) { +- return '[Circular]'; +- } +- default: +- return x; +- } +- }); +- for (var x = args[i]; i < len; x = args[++i]) { +- if (isNull(x) || !isObject(x)) { +- str += ' ' + x; +- } else { +- str += ' ' + inspect(x); +- } +- } +- return str; +-}; +- +- +-// Mark that a method should not be used. +-// Returns a modified function which warns once by default. +-// If --no-deprecation is set, then it is a no-op. +-exports.deprecate = function(fn, msg) { +- // Allow for deprecating things in the process of starting up. +- if (isUndefined(global.process)) { +- return function() { +- return exports.deprecate(fn, msg).apply(this, arguments); +- }; +- } +- +- if (process.noDeprecation === true) { +- return fn; +- } +- +- var warned = false; +- function deprecated() { +- if (!warned) { +- if (process.throwDeprecation) { +- throw new Error(msg); +- } else if (process.traceDeprecation) { +- console.trace(msg); +- } else { +- console.error(msg); +- } +- warned = true; +- } +- return fn.apply(this, arguments); +- } +- +- return deprecated; +-}; +- +- +-var debugs = {}; +-var debugEnviron; +-exports.debuglog = function(set) { +- if (isUndefined(debugEnviron)) +- debugEnviron = process.env.NODE_DEBUG || ''; +- set = set.toUpperCase(); +- if (!debugs[set]) { +- if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { +- var pid = process.pid; +- debugs[set] = function() { +- var msg = exports.format.apply(exports, arguments); +- console.error('%s %d: %s', set, pid, msg); +- }; +- } else { +- debugs[set] = function() {}; +- } +- } +- return debugs[set]; +-}; +- +- +-/** +- * Echos the value of a value. Trys to print the value out +- * in the best way possible given the different types. +- * +- * @param {Object} obj The object to print out. +- * @param {Object} opts Optional options object that alters the output. +- */ +-/* legacy: obj, showHidden, depth, colors*/ +-function inspect(obj, opts) { +- // default options +- var ctx = { +- seen: [], +- stylize: stylizeNoColor +- }; +- // legacy... +- if (arguments.length >= 3) ctx.depth = arguments[2]; +- if (arguments.length >= 4) ctx.colors = arguments[3]; +- if (isBoolean(opts)) { +- // legacy... +- ctx.showHidden = opts; +- } else if (opts) { +- // got an "options" object +- exports._extend(ctx, opts); +- } +- // set default options +- if (isUndefined(ctx.showHidden)) ctx.showHidden = false; +- if (isUndefined(ctx.depth)) ctx.depth = 2; +- if (isUndefined(ctx.colors)) ctx.colors = false; +- if (isUndefined(ctx.customInspect)) ctx.customInspect = true; +- if (ctx.colors) ctx.stylize = stylizeWithColor; +- return formatValue(ctx, obj, ctx.depth); +-} +-exports.inspect = inspect; +- +- +-// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +-inspect.colors = { +- 'bold' : [1, 22], +- 'italic' : [3, 23], +- 'underline' : [4, 24], +- 'inverse' : [7, 27], +- 'white' : [37, 39], +- 'grey' : [90, 39], +- 'black' : [30, 39], +- 'blue' : [34, 39], +- 'cyan' : [36, 39], +- 'green' : [32, 39], +- 'magenta' : [35, 39], +- 'red' : [31, 39], +- 'yellow' : [33, 39] +-}; +- +-// Don't use 'blue' not visible on cmd.exe +-inspect.styles = { +- 'special': 'cyan', +- 'number': 'yellow', +- 'boolean': 'yellow', +- 'undefined': 'grey', +- 'null': 'bold', +- 'string': 'green', +- 'date': 'magenta', +- // "name": intentionally not styling +- 'regexp': 'red' +-}; +- +- +-function stylizeWithColor(str, styleType) { +- var style = inspect.styles[styleType]; +- +- if (style) { +- return '\u001b[' + inspect.colors[style][0] + 'm' + str + +- '\u001b[' + inspect.colors[style][1] + 'm'; +- } else { +- return str; +- } +-} +- +- +-function stylizeNoColor(str, styleType) { +- return str; +-} +- +- +-function arrayToHash(array) { +- var hash = {}; +- +- array.forEach(function(val, idx) { +- hash[val] = true; +- }); +- +- return hash; +-} +- +- +-function formatValue(ctx, value, recurseTimes) { +- // Provide a hook for user-specified inspect functions. +- // Check that value is an object with an inspect function on it +- if (ctx.customInspect && +- value && +- isFunction(value.inspect) && +- // Filter out the util module, it's inspect function is special +- value.inspect !== exports.inspect && +- // Also filter out any prototype objects using the circular check. +- !(value.constructor && value.constructor.prototype === value)) { +- var ret = value.inspect(recurseTimes, ctx); +- if (!isString(ret)) { +- ret = formatValue(ctx, ret, recurseTimes); +- } +- return ret; +- } +- +- // Primitive types cannot have properties +- var primitive = formatPrimitive(ctx, value); +- if (primitive) { +- return primitive; +- } +- +- // Look up the keys of the object. +- var keys = Object.keys(value); +- var visibleKeys = arrayToHash(keys); +- +- if (ctx.showHidden) { +- keys = Object.getOwnPropertyNames(value); +- } +- +- // Some type of object without properties can be shortcutted. +- if (keys.length === 0) { +- if (isFunction(value)) { +- var name = value.name ? ': ' + value.name : ''; +- return ctx.stylize('[Function' + name + ']', 'special'); +- } +- if (isRegExp(value)) { +- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); +- } +- if (isDate(value)) { +- return ctx.stylize(Date.prototype.toString.call(value), 'date'); +- } +- if (isError(value)) { +- return formatError(value); +- } +- } +- +- var base = '', array = false, braces = ['{', '}']; +- +- // Make Array say that they are Array +- if (isArray(value)) { +- array = true; +- braces = ['[', ']']; +- } +- +- // Make functions say that they are functions +- if (isFunction(value)) { +- var n = value.name ? ': ' + value.name : ''; +- base = ' [Function' + n + ']'; +- } +- +- // Make RegExps say that they are RegExps +- if (isRegExp(value)) { +- base = ' ' + RegExp.prototype.toString.call(value); +- } +- +- // Make dates with properties first say the date +- if (isDate(value)) { +- base = ' ' + Date.prototype.toUTCString.call(value); +- } +- +- // Make error with message first say the error +- if (isError(value)) { +- base = ' ' + formatError(value); +- } +- +- if (keys.length === 0 && (!array || value.length == 0)) { +- return braces[0] + base + braces[1]; +- } +- +- if (recurseTimes < 0) { +- if (isRegExp(value)) { +- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); +- } else { +- return ctx.stylize('[Object]', 'special'); +- } +- } +- +- ctx.seen.push(value); +- +- var output; +- if (array) { +- output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); +- } else { +- output = keys.map(function(key) { +- return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); +- }); +- } +- +- ctx.seen.pop(); +- +- return reduceToSingleString(output, base, braces); +-} +- +- +-function formatPrimitive(ctx, value) { +- if (isUndefined(value)) +- return ctx.stylize('undefined', 'undefined'); +- if (isString(value)) { +- var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') +- .replace(/'/g, "\\'") +- .replace(/\\"/g, '"') + '\''; +- return ctx.stylize(simple, 'string'); +- } +- if (isNumber(value)) { +- // Format -0 as '-0'. Strict equality won't distinguish 0 from -0, +- // so instead we use the fact that 1 / -0 < 0 whereas 1 / 0 > 0 . +- if (value === 0 && 1 / value < 0) +- return ctx.stylize('-0', 'number'); +- return ctx.stylize('' + value, 'number'); +- } +- if (isBoolean(value)) +- return ctx.stylize('' + value, 'boolean'); +- // For some reason typeof null is "object", so special case here. +- if (isNull(value)) +- return ctx.stylize('null', 'null'); +-} +- +- +-function formatError(value) { +- return '[' + Error.prototype.toString.call(value) + ']'; +-} +- +- +-function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { +- var output = []; +- for (var i = 0, l = value.length; i < l; ++i) { +- if (hasOwnProperty(value, String(i))) { +- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, +- String(i), true)); +- } else { +- output.push(''); +- } +- } +- keys.forEach(function(key) { +- if (!key.match(/^\d+$/)) { +- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, +- key, true)); +- } +- }); +- return output; +-} +- +- +-function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { +- var name, str, desc; +- desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; +- if (desc.get) { +- if (desc.set) { +- str = ctx.stylize('[Getter/Setter]', 'special'); +- } else { +- str = ctx.stylize('[Getter]', 'special'); +- } +- } else { +- if (desc.set) { +- str = ctx.stylize('[Setter]', 'special'); +- } +- } +- if (!hasOwnProperty(visibleKeys, key)) { +- name = '[' + key + ']'; +- } +- if (!str) { +- if (ctx.seen.indexOf(desc.value) < 0) { +- if (isNull(recurseTimes)) { +- str = formatValue(ctx, desc.value, null); +- } else { +- str = formatValue(ctx, desc.value, recurseTimes - 1); +- } +- if (str.indexOf('\n') > -1) { +- if (array) { +- str = str.split('\n').map(function(line) { +- return ' ' + line; +- }).join('\n').substr(2); +- } else { +- str = '\n' + str.split('\n').map(function(line) { +- return ' ' + line; +- }).join('\n'); +- } +- } +- } else { +- str = ctx.stylize('[Circular]', 'special'); +- } +- } +- if (isUndefined(name)) { +- if (array && key.match(/^\d+$/)) { +- return str; +- } +- name = JSON.stringify('' + key); +- if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { +- name = name.substr(1, name.length - 2); +- name = ctx.stylize(name, 'name'); +- } else { +- name = name.replace(/'/g, "\\'") +- .replace(/\\"/g, '"') +- .replace(/(^"|"$)/g, "'"); +- name = ctx.stylize(name, 'string'); +- } +- } +- +- return name + ': ' + str; +-} +- +- +-function reduceToSingleString(output, base, braces) { +- var numLinesEst = 0; +- var length = output.reduce(function(prev, cur) { +- numLinesEst++; +- if (cur.indexOf('\n') >= 0) numLinesEst++; +- return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; +- }, 0); +- +- if (length > 60) { +- return braces[0] + +- (base === '' ? '' : base + '\n ') + +- ' ' + +- output.join(',\n ') + +- ' ' + +- braces[1]; +- } +- +- return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +-} +- +- + // NOTE: These type checking functions intentionally don't use `instanceof` + // because it is fragile and can be easily faked with `Object.create()`. + function isArray(ar) { +@@ -522,166 +98,10 @@ function isPrimitive(arg) { + exports.isPrimitive = isPrimitive; + + function isBuffer(arg) { +- return arg instanceof Buffer; ++ return Buffer.isBuffer(arg); + } + exports.isBuffer = isBuffer; + + function objectToString(o) { + return Object.prototype.toString.call(o); +-} +- +- +-function pad(n) { +- return n < 10 ? '0' + n.toString(10) : n.toString(10); +-} +- +- +-var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', +- 'Oct', 'Nov', 'Dec']; +- +-// 26 Feb 16:19:34 +-function timestamp() { +- var d = new Date(); +- var time = [pad(d.getHours()), +- pad(d.getMinutes()), +- pad(d.getSeconds())].join(':'); +- return [d.getDate(), months[d.getMonth()], time].join(' '); +-} +- +- +-// log is just a thin wrapper to console.log that prepends a timestamp +-exports.log = function() { +- console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +-}; +- +- +-/** +- * Inherit the prototype methods from one constructor into another. +- * +- * The Function.prototype.inherits from lang.js rewritten as a standalone +- * function (not on Function.prototype). NOTE: If this file is to be loaded +- * during bootstrapping this function needs to be rewritten using some native +- * functions as prototype setup using normal JavaScript does not work as +- * expected during bootstrapping (see mirror.js in r114903). +- * +- * @param {function} ctor Constructor function which needs to inherit the +- * prototype. +- * @param {function} superCtor Constructor function to inherit prototype from. +- */ +-exports.inherits = function(ctor, superCtor) { +- ctor.super_ = superCtor; +- ctor.prototype = Object.create(superCtor.prototype, { +- constructor: { +- value: ctor, +- enumerable: false, +- writable: true, +- configurable: true +- } +- }); +-}; +- +-exports._extend = function(origin, add) { +- // Don't do anything if add isn't an object +- if (!add || !isObject(add)) return origin; +- +- var keys = Object.keys(add); +- var i = keys.length; +- while (i--) { +- origin[keys[i]] = add[keys[i]]; +- } +- return origin; +-}; +- +-function hasOwnProperty(obj, prop) { +- return Object.prototype.hasOwnProperty.call(obj, prop); +-} +- +- +-// Deprecated old stuff. +- +-exports.p = exports.deprecate(function() { +- for (var i = 0, len = arguments.length; i < len; ++i) { +- console.error(exports.inspect(arguments[i])); +- } +-}, 'util.p: Use console.error() instead'); +- +- +-exports.exec = exports.deprecate(function() { +- return require('child_process').exec.apply(this, arguments); +-}, 'util.exec is now called `child_process.exec`.'); +- +- +-exports.print = exports.deprecate(function() { +- for (var i = 0, len = arguments.length; i < len; ++i) { +- process.stdout.write(String(arguments[i])); +- } +-}, 'util.print: Use console.log instead'); +- +- +-exports.puts = exports.deprecate(function() { +- for (var i = 0, len = arguments.length; i < len; ++i) { +- process.stdout.write(arguments[i] + '\n'); +- } +-}, 'util.puts: Use console.log instead'); +- +- +-exports.debug = exports.deprecate(function(x) { +- process.stderr.write('DEBUG: ' + x + '\n'); +-}, 'util.debug: Use console.error instead'); +- +- +-exports.error = exports.deprecate(function(x) { +- for (var i = 0, len = arguments.length; i < len; ++i) { +- process.stderr.write(arguments[i] + '\n'); +- } +-}, 'util.error: Use console.error instead'); +- +- +-exports.pump = exports.deprecate(function(readStream, writeStream, callback) { +- var callbackCalled = false; +- +- function call(a, b, c) { +- if (callback && !callbackCalled) { +- callback(a, b, c); +- callbackCalled = true; +- } +- } +- +- readStream.addListener('data', function(chunk) { +- if (writeStream.write(chunk) === false) readStream.pause(); +- }); +- +- writeStream.addListener('drain', function() { +- readStream.resume(); +- }); +- +- readStream.addListener('end', function() { +- writeStream.end(); +- }); +- +- readStream.addListener('close', function() { +- call(); +- }); +- +- readStream.addListener('error', function(err) { +- writeStream.end(); +- call(err); +- }); +- +- writeStream.addListener('error', function(err) { +- readStream.destroy(); +- call(err); +- }); +-}, 'util.pump(): Use readableStream.pipe() instead'); +- +- +-var uv; +-exports._errnoException = function(err, syscall) { +- if (isUndefined(uv)) uv = process.binding('uv'); +- var errname = uv.errname(err); +- var e = new Error(syscall + ' ' + errname); +- e.code = errname; +- e.errno = errname; +- e.syscall = syscall; +- return e; +-}; ++}
@@ -0,0 +1,107 @@
+// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. + +function isArray(arg) { + if (Array.isArray) { + return Array.isArray(arg); + } + return objectToString(arg) === '[object Array]'; +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = Buffer.isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +}
@@ -0,0 +1,60 @@
+{ + "name": "core-util-is", + "version": "1.0.2", + "description": "The `util.is*` functions introduced in Node v0.12.", + "main": "lib/util.js", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/core-util-is.git" + }, + "keywords": [ + "util", + "isBuffer", + "isArray", + "isNumber", + "isString", + "isRegExp", + "isThis", + "isThat", + "polyfill" + ], + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/isaacs/core-util-is/issues" + }, + "scripts": { + "test": "tap test.js" + }, + "devDependencies": { + "tap": "^2.3.0" + }, + "gitHead": "a177da234df5638b363ddc15fa324619a38577c8", + "homepage": "https://github.com/isaacs/core-util-is#readme", + "_id": "core-util-is@1.0.2", + "_shasum": "b5fd54220aa2bc5ab57aab7140c940754503c1a7", + "_from": "core-util-is@>=1.0.0 <1.1.0", + "_npmVersion": "3.3.2", + "_nodeVersion": "4.0.0", + "_npmUser": { + "name": "isaacs", + "email": "i@izs.me" + }, + "dist": { + "shasum": "b5fd54220aa2bc5ab57aab7140c940754503c1a7", + "tarball": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "maintainers": [ + { + "name": "isaacs", + "email": "i@izs.me" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,68 @@
+var assert = require('tap'); + +var t = require('./lib/util'); + +assert.equal(t.isArray([]), true); +assert.equal(t.isArray({}), false); + +assert.equal(t.isBoolean(null), false); +assert.equal(t.isBoolean(true), true); +assert.equal(t.isBoolean(false), true); + +assert.equal(t.isNull(null), true); +assert.equal(t.isNull(undefined), false); +assert.equal(t.isNull(false), false); +assert.equal(t.isNull(), false); + +assert.equal(t.isNullOrUndefined(null), true); +assert.equal(t.isNullOrUndefined(undefined), true); +assert.equal(t.isNullOrUndefined(false), false); +assert.equal(t.isNullOrUndefined(), true); + +assert.equal(t.isNumber(null), false); +assert.equal(t.isNumber('1'), false); +assert.equal(t.isNumber(1), true); + +assert.equal(t.isString(null), false); +assert.equal(t.isString('1'), true); +assert.equal(t.isString(1), false); + +assert.equal(t.isSymbol(null), false); +assert.equal(t.isSymbol('1'), false); +assert.equal(t.isSymbol(1), false); +assert.equal(t.isSymbol(Symbol()), true); + +assert.equal(t.isUndefined(null), false); +assert.equal(t.isUndefined(undefined), true); +assert.equal(t.isUndefined(false), false); +assert.equal(t.isUndefined(), true); + +assert.equal(t.isRegExp(null), false); +assert.equal(t.isRegExp('1'), false); +assert.equal(t.isRegExp(new RegExp()), true); + +assert.equal(t.isObject({}), true); +assert.equal(t.isObject([]), true); +assert.equal(t.isObject(new RegExp()), true); +assert.equal(t.isObject(new Date()), true); + +assert.equal(t.isDate(null), false); +assert.equal(t.isDate('1'), false); +assert.equal(t.isDate(new Date()), true); + +assert.equal(t.isError(null), false); +assert.equal(t.isError({ err: true }), false); +assert.equal(t.isError(new Error()), true); + +assert.equal(t.isFunction(null), false); +assert.equal(t.isFunction({ }), false); +assert.equal(t.isFunction(function() {}), true); + +assert.equal(t.isPrimitive(null), true); +assert.equal(t.isPrimitive(''), true); +assert.equal(t.isPrimitive(0), true); +assert.equal(t.isPrimitive(new Date()), false); + +assert.equal(t.isBuffer(null), false); +assert.equal(t.isBuffer({}), false); +assert.equal(t.isBuffer(new Buffer(0)), true);
@@ -0,0 +1,54 @@
+ +# isarray + +`Array#isArray` for older browsers. + +## Usage + +```js +var isArray = require('isarray'); + +console.log(isArray([])); // => true +console.log(isArray({})); // => false +``` + +## Installation + +With [npm](http://npmjs.org) do + +```bash +$ npm install isarray +``` + +Then bundle for the browser with +[browserify](https://github.com/substack/browserify). + +With [component](http://component.io) do + +```bash +$ component install juliangruber/isarray +``` + +## License + +(MIT) + +Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.
@@ -0,0 +1,209 @@
+ +/** + * Require the given path. + * + * @param {String} path + * @return {Object} exports + * @api public + */ + +function require(path, parent, orig) { + var resolved = require.resolve(path); + + // lookup failed + if (null == resolved) { + orig = orig || path; + parent = parent || 'root'; + var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); + err.path = orig; + err.parent = parent; + err.require = true; + throw err; + } + + var module = require.modules[resolved]; + + // perform real require() + // by invoking the module's + // registered function + if (!module.exports) { + module.exports = {}; + module.client = module.component = true; + module.call(this, module.exports, require.relative(resolved), module); + } + + return module.exports; +} + +/** + * Registered modules. + */ + +require.modules = {}; + +/** + * Registered aliases. + */ + +require.aliases = {}; + +/** + * Resolve `path`. + * + * Lookup: + * + * - PATH/index.js + * - PATH.js + * - PATH + * + * @param {String} path + * @return {String} path or null + * @api private + */ + +require.resolve = function(path) { + if (path.charAt(0) === '/') path = path.slice(1); + var index = path + '/index.js'; + + var paths = [ + path, + path + '.js', + path + '.json', + path + '/index.js', + path + '/index.json' + ]; + + for (var i = 0; i < paths.length; i++) { + var path = paths[i]; + if (require.modules.hasOwnProperty(path)) return path; + } + + if (require.aliases.hasOwnProperty(index)) { + return require.aliases[index]; + } +}; + +/** + * Normalize `path` relative to the current path. + * + * @param {String} curr + * @param {String} path + * @return {String} + * @api private + */ + +require.normalize = function(curr, path) { + var segs = []; + + if ('.' != path.charAt(0)) return path; + + curr = curr.split('/'); + path = path.split('/'); + + for (var i = 0; i < path.length; ++i) { + if ('..' == path[i]) { + curr.pop(); + } else if ('.' != path[i] && '' != path[i]) { + segs.push(path[i]); + } + } + + return curr.concat(segs).join('/'); +}; + +/** + * Register module at `path` with callback `definition`. + * + * @param {String} path + * @param {Function} definition + * @api private + */ + +require.register = function(path, definition) { + require.modules[path] = definition; +}; + +/** + * Alias a module definition. + * + * @param {String} from + * @param {String} to + * @api private + */ + +require.alias = function(from, to) { + if (!require.modules.hasOwnProperty(from)) { + throw new Error('Failed to alias "' + from + '", it does not exist'); + } + require.aliases[to] = from; +}; + +/** + * Return a require function relative to the `parent` path. + * + * @param {String} parent + * @return {Function} + * @api private + */ + +require.relative = function(parent) { + var p = require.normalize(parent, '..'); + + /** + * lastIndexOf helper. + */ + + function lastIndexOf(arr, obj) { + var i = arr.length; + while (i--) { + if (arr[i] === obj) return i; + } + return -1; + } + + /** + * The relative require() itself. + */ + + function localRequire(path) { + var resolved = localRequire.resolve(path); + return require(resolved, parent, path); + } + + /** + * Resolve relative to the parent. + */ + + localRequire.resolve = function(path) { + var c = path.charAt(0); + if ('/' == c) return path.slice(1); + if ('.' == c) return require.normalize(p, path); + + // resolve deps by returning + // the dep in the nearest "deps" + // directory + var segs = parent.split('/'); + var i = lastIndexOf(segs, 'deps') + 1; + if (!i) i = 0; + path = segs.slice(0, i + 1).join('/') + '/deps/' + path; + return path; + }; + + /** + * Check if module is defined at `path`. + */ + + localRequire.exists = function(path) { + return require.modules.hasOwnProperty(localRequire.resolve(path)); + }; + + return localRequire; +}; +require.register("isarray/index.js", function(exports, require, module){ +module.exports = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) == '[object Array]'; +}; + +}); +require.alias("isarray/index.js", "isarray/index.js"); +
@@ -0,0 +1,19 @@
+{ + "name" : "isarray", + "description" : "Array#isArray for older browsers", + "version" : "0.0.1", + "repository" : "juliangruber/isarray", + "homepage": "https://github.com/juliangruber/isarray", + "main" : "index.js", + "scripts" : [ + "index.js" + ], + "dependencies" : {}, + "keywords": ["browser","isarray","array"], + "author": { + "name": "Julian Gruber", + "email": "mail@juliangruber.com", + "url": "http://juliangruber.com" + }, + "license": "MIT" +}
@@ -0,0 +1,3 @@
+module.exports = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) == '[object Array]'; +};
@@ -0,0 +1,53 @@
+{ + "name": "isarray", + "description": "Array#isArray for older browsers", + "version": "0.0.1", + "repository": { + "type": "git", + "url": "git://github.com/juliangruber/isarray.git" + }, + "homepage": "https://github.com/juliangruber/isarray", + "main": "index.js", + "scripts": { + "test": "tap test/*.js" + }, + "dependencies": {}, + "devDependencies": { + "tap": "*" + }, + "keywords": [ + "browser", + "isarray", + "array" + ], + "author": { + "name": "Julian Gruber", + "email": "mail@juliangruber.com", + "url": "http://juliangruber.com" + }, + "license": "MIT", + "_id": "isarray@0.0.1", + "dist": { + "shasum": "8a18acfca9a8f4177e09abfc6038939b05d1eedf", + "tarball": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "_from": "isarray@0.0.1", + "_npmVersion": "1.2.18", + "_npmUser": { + "name": "juliangruber", + "email": "julian@juliangruber.com" + }, + "maintainers": [ + { + "name": "juliangruber", + "email": "julian@juliangruber.com" + } + ], + "directories": {}, + "_shasum": "8a18acfca9a8f4177e09abfc6038939b05d1eedf", + "_resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "bugs": { + "url": "https://github.com/juliangruber/isarray/issues" + }, + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,20 @@
+Copyright Joyent, Inc. and other Node contributors. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,7 @@
+**string_decoder.js** (`require('string_decoder')`) from Node.js core + +Copyright Joyent, Inc. and other Node contributors. See LICENCE file for details. + +Version numbers match the versions found in Node core, e.g. 0.10.24 matches Node 0.10.24, likewise 0.11.10 matches Node 0.11.10. **Prefer the stable version over the unstable.** + +The *build/* directory contains a build script that will scrape the source from the [joyent/node](https://github.com/joyent/node) repo given a specific Node version.
@@ -0,0 +1,221 @@
+// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var Buffer = require('buffer').Buffer; + +var isBufferEncoding = Buffer.isEncoding + || function(encoding) { + switch (encoding && encoding.toLowerCase()) { + case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; + default: return false; + } + } + + +function assertEncoding(encoding) { + if (encoding && !isBufferEncoding(encoding)) { + throw new Error('Unknown encoding: ' + encoding); + } +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. CESU-8 is handled as part of the UTF-8 encoding. +// +// @TODO Handling all encodings inside a single object makes it very difficult +// to reason about this code, so it should be split up in the future. +// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code +// points as used by CESU-8. +var StringDecoder = exports.StringDecoder = function(encoding) { + this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); + assertEncoding(encoding); + switch (this.encoding) { + case 'utf8': + // CESU-8 represents each of Surrogate Pair by 3-bytes + this.surrogateSize = 3; + break; + case 'ucs2': + case 'utf16le': + // UTF-16 represents each of Surrogate Pair by 2-bytes + this.surrogateSize = 2; + this.detectIncompleteChar = utf16DetectIncompleteChar; + break; + case 'base64': + // Base-64 stores 3 bytes in 4 chars, and pads the remainder. + this.surrogateSize = 3; + this.detectIncompleteChar = base64DetectIncompleteChar; + break; + default: + this.write = passThroughWrite; + return; + } + + // Enough space to store all bytes of a single character. UTF-8 needs 4 + // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate). + this.charBuffer = new Buffer(6); + // Number of bytes received for the current incomplete multi-byte character. + this.charReceived = 0; + // Number of bytes expected for the current incomplete multi-byte character. + this.charLength = 0; +}; + + +// write decodes the given buffer and returns it as JS string that is +// guaranteed to not contain any partial multi-byte characters. Any partial +// character found at the end of the buffer is buffered up, and will be +// returned when calling write again with the remaining bytes. +// +// Note: Converting a Buffer containing an orphan surrogate to a String +// currently works, but converting a String to a Buffer (via `new Buffer`, or +// Buffer#write) will replace incomplete surrogates with the unicode +// replacement character. See https://codereview.chromium.org/121173009/ . +StringDecoder.prototype.write = function(buffer) { + var charStr = ''; + // if our last write ended with an incomplete multibyte character + while (this.charLength) { + // determine how many remaining bytes this buffer has to offer for this char + var available = (buffer.length >= this.charLength - this.charReceived) ? + this.charLength - this.charReceived : + buffer.length; + + // add the new bytes to the char buffer + buffer.copy(this.charBuffer, this.charReceived, 0, available); + this.charReceived += available; + + if (this.charReceived < this.charLength) { + // still not enough chars in this buffer? wait for more ... + return ''; + } + + // remove bytes belonging to the current character from the buffer + buffer = buffer.slice(available, buffer.length); + + // get the character that was split + charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); + + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + var charCode = charStr.charCodeAt(charStr.length - 1); + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + this.charLength += this.surrogateSize; + charStr = ''; + continue; + } + this.charReceived = this.charLength = 0; + + // if there are no more bytes in this buffer, just emit our char + if (buffer.length === 0) { + return charStr; + } + break; + } + + // determine and set charLength / charReceived + this.detectIncompleteChar(buffer); + + var end = buffer.length; + if (this.charLength) { + // buffer the incomplete character bytes we got + buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end); + end -= this.charReceived; + } + + charStr += buffer.toString(this.encoding, 0, end); + + var end = charStr.length - 1; + var charCode = charStr.charCodeAt(end); + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + var size = this.surrogateSize; + this.charLength += size; + this.charReceived += size; + this.charBuffer.copy(this.charBuffer, size, 0, size); + buffer.copy(this.charBuffer, 0, 0, size); + return charStr.substring(0, end); + } + + // or just emit the charStr + return charStr; +}; + +// detectIncompleteChar determines if there is an incomplete UTF-8 character at +// the end of the given buffer. If so, it sets this.charLength to the byte +// length that character, and sets this.charReceived to the number of bytes +// that are available for this character. +StringDecoder.prototype.detectIncompleteChar = function(buffer) { + // determine how many bytes we have to check at the end of this buffer + var i = (buffer.length >= 3) ? 3 : buffer.length; + + // Figure out if one of the last i bytes of our buffer announces an + // incomplete char. + for (; i > 0; i--) { + var c = buffer[buffer.length - i]; + + // See http://en.wikipedia.org/wiki/UTF-8#Description + + // 110XXXXX + if (i == 1 && c >> 5 == 0x06) { + this.charLength = 2; + break; + } + + // 1110XXXX + if (i <= 2 && c >> 4 == 0x0E) { + this.charLength = 3; + break; + } + + // 11110XXX + if (i <= 3 && c >> 3 == 0x1E) { + this.charLength = 4; + break; + } + } + this.charReceived = i; +}; + +StringDecoder.prototype.end = function(buffer) { + var res = ''; + if (buffer && buffer.length) + res = this.write(buffer); + + if (this.charReceived) { + var cr = this.charReceived; + var buf = this.charBuffer; + var enc = this.encoding; + res += buf.slice(0, cr).toString(enc); + } + + return res; +}; + +function passThroughWrite(buffer) { + return buffer.toString(this.encoding); +} + +function utf16DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 2; + this.charLength = this.charReceived ? 2 : 0; +} + +function base64DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 3; + this.charLength = this.charReceived ? 3 : 0; +}
@@ -0,0 +1,54 @@
+{ + "name": "string_decoder", + "version": "0.10.31", + "description": "The string_decoder module from Node core", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "tap": "~0.4.8" + }, + "scripts": { + "test": "tap test/simple/*.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/rvagg/string_decoder.git" + }, + "homepage": "https://github.com/rvagg/string_decoder", + "keywords": [ + "string", + "decoder", + "browser", + "browserify" + ], + "license": "MIT", + "gitHead": "d46d4fd87cf1d06e031c23f1ba170ca7d4ade9a0", + "bugs": { + "url": "https://github.com/rvagg/string_decoder/issues" + }, + "_id": "string_decoder@0.10.31", + "_shasum": "62e203bc41766c6c28c9fc84301dab1c5310fa94", + "_from": "string_decoder@>=0.10.0 <0.11.0", + "_npmVersion": "1.4.23", + "_npmUser": { + "name": "rvagg", + "email": "rod@vagg.org" + }, + "maintainers": [ + { + "name": "substack", + "email": "mail@substack.net" + }, + { + "name": "rvagg", + "email": "rod@vagg.org" + } + ], + "dist": { + "shasum": "62e203bc41766c6c28c9fc84301dab1c5310fa94", + "tarball": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,79 @@
+{ + "name": "readable-stream", + "version": "1.1.14", + "description": "Streams3, a user-land copy of the stream library from Node.js v0.11.x", + "main": "readable.js", + "dependencies": { + "core-util-is": "~1.0.0", + "isarray": "0.0.1", + "string_decoder": "~0.10.x", + "inherits": "~2.0.1" + }, + "devDependencies": { + "tap": "~0.2.6" + }, + "scripts": { + "test": "tap test/simple/*.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/readable-stream.git" + }, + "keywords": [ + "readable", + "stream", + "pipe" + ], + "browser": { + "util": false + }, + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "license": "MIT", + "gitHead": "52550840cb1d6e8a98ef9a909a4bea360bc6f7da", + "bugs": { + "url": "https://github.com/isaacs/readable-stream/issues" + }, + "_id": "readable-stream@1.1.14", + "_shasum": "7cf4c54ef648e3813084c636dd2079e166c081d9", + "_from": "readable-stream@>=1.1.9 <1.2.0", + "_npmVersion": "3.8.3", + "_nodeVersion": "5.10.1", + "_npmUser": { + "name": "cwmma", + "email": "calvin.metcalf@gmail.com" + }, + "dist": { + "shasum": "7cf4c54ef648e3813084c636dd2079e166c081d9", + "tarball": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" + }, + "maintainers": [ + { + "name": "isaacs", + "email": "isaacs@npmjs.com" + }, + { + "name": "tootallnate", + "email": "nathan@tootallnate.net" + }, + { + "name": "rvagg", + "email": "rod@vagg.org" + }, + { + "name": "cwmma", + "email": "calvin.metcalf@gmail.com" + } + ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/readable-stream-1.1.14.tgz_1460563293219_0.5682175166439265" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "readme": "ERROR: No README data found!", + "homepage": "https://github.com/isaacs/readable-stream#readme" +}
@@ -0,0 +1,1 @@
+module.exports = require("./lib/_stream_passthrough.js")
@@ -0,0 +1,10 @@
+exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = require('stream'); +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); +if (!process.browser && process.env.READABLE_STREAM === 'disable') { + module.exports = require('stream'); +}
@@ -0,0 +1,1 @@
+module.exports = require("./lib/_stream_transform.js")
@@ -0,0 +1,1 @@
+module.exports = require("./lib/_stream_writable.js")
@@ -0,0 +1,4 @@
+language: node_js +node_js: + - "0.8" + - "0.10"
@@ -0,0 +1,35 @@
+/* + Copyright (c) 2010, Linden Research, Inc. + Copyright (c) 2012, Joshua Bell + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + $/LicenseInfo$ + */ + +// Original can be found at: +// https://bitbucket.org/lindenlab/llsd +// Modifications by Joshua Bell inexorabletash@gmail.com +// https://github.com/inexorabletash/polyfill + +// ES3/ES5 implementation of the Krhonos Typed Array Specification +// Ref: http://www.khronos.org/registry/typedarray/specs/latest/ +// Date: 2011-02-01 +// +// Variations: +// * Allows typed_array.get/set() as alias for subscripts (typed_array[])
@@ -0,0 +1,4 @@
+var Uint8Array = require('../').Uint8Array; +var ua = new Uint8Array(5); +ua[1] = 256 + 55; +console.log(ua[1]);
@@ -0,0 +1,630 @@
+var undefined = (void 0); // Paranoia + +// Beyond this value, index getters/setters (i.e. array[0], array[1]) are so slow to +// create, and consume so much memory, that the browser appears frozen. +var MAX_ARRAY_LENGTH = 1e5; + +// Approximations of internal ECMAScript conversion functions +var ECMAScript = (function() { + // Stash a copy in case other scripts modify these + var opts = Object.prototype.toString, + ophop = Object.prototype.hasOwnProperty; + + return { + // Class returns internal [[Class]] property, used to avoid cross-frame instanceof issues: + Class: function(v) { return opts.call(v).replace(/^\[object *|\]$/g, ''); }, + HasProperty: function(o, p) { return p in o; }, + HasOwnProperty: function(o, p) { return ophop.call(o, p); }, + IsCallable: function(o) { return typeof o === 'function'; }, + ToInt32: function(v) { return v >> 0; }, + ToUint32: function(v) { return v >>> 0; } + }; +}()); + +// Snapshot intrinsics +var LN2 = Math.LN2, + abs = Math.abs, + floor = Math.floor, + log = Math.log, + min = Math.min, + pow = Math.pow, + round = Math.round; + +// ES5: lock down object properties +function configureProperties(obj) { + if (getOwnPropNames && defineProp) { + var props = getOwnPropNames(obj), i; + for (i = 0; i < props.length; i += 1) { + defineProp(obj, props[i], { + value: obj[props[i]], + writable: false, + enumerable: false, + configurable: false + }); + } + } +} + +// emulate ES5 getter/setter API using legacy APIs +// http://blogs.msdn.com/b/ie/archive/2010/09/07/transitioning-existing-code-to-the-es5-getter-setter-apis.aspx +// (second clause tests for Object.defineProperty() in IE<9 that only supports extending DOM prototypes, but +// note that IE<9 does not support __defineGetter__ or __defineSetter__ so it just renders the method harmless) +var defineProp +if (Object.defineProperty && (function() { + try { + Object.defineProperty({}, 'x', {}); + return true; + } catch (e) { + return false; + } + })()) { + defineProp = Object.defineProperty; +} else { + defineProp = function(o, p, desc) { + if (!o === Object(o)) throw new TypeError("Object.defineProperty called on non-object"); + if (ECMAScript.HasProperty(desc, 'get') && Object.prototype.__defineGetter__) { Object.prototype.__defineGetter__.call(o, p, desc.get); } + if (ECMAScript.HasProperty(desc, 'set') && Object.prototype.__defineSetter__) { Object.prototype.__defineSetter__.call(o, p, desc.set); } + if (ECMAScript.HasProperty(desc, 'value')) { o[p] = desc.value; } + return o; + }; +} + +var getOwnPropNames = Object.getOwnPropertyNames || function (o) { + if (o !== Object(o)) throw new TypeError("Object.getOwnPropertyNames called on non-object"); + var props = [], p; + for (p in o) { + if (ECMAScript.HasOwnProperty(o, p)) { + props.push(p); + } + } + return props; +}; + +// ES5: Make obj[index] an alias for obj._getter(index)/obj._setter(index, value) +// for index in 0 ... obj.length +function makeArrayAccessors(obj) { + if (!defineProp) { return; } + + if (obj.length > MAX_ARRAY_LENGTH) throw new RangeError("Array too large for polyfill"); + + function makeArrayAccessor(index) { + defineProp(obj, index, { + 'get': function() { return obj._getter(index); }, + 'set': function(v) { obj._setter(index, v); }, + enumerable: true, + configurable: false + }); + } + + var i; + for (i = 0; i < obj.length; i += 1) { + makeArrayAccessor(i); + } +} + +// Internal conversion functions: +// pack<Type>() - take a number (interpreted as Type), output a byte array +// unpack<Type>() - take a byte array, output a Type-like number + +function as_signed(value, bits) { var s = 32 - bits; return (value << s) >> s; } +function as_unsigned(value, bits) { var s = 32 - bits; return (value << s) >>> s; } + +function packI8(n) { return [n & 0xff]; } +function unpackI8(bytes) { return as_signed(bytes[0], 8); } + +function packU8(n) { return [n & 0xff]; } +function unpackU8(bytes) { return as_unsigned(bytes[0], 8); } + +function packU8Clamped(n) { n = round(Number(n)); return [n < 0 ? 0 : n > 0xff ? 0xff : n & 0xff]; } + +function packI16(n) { return [(n >> 8) & 0xff, n & 0xff]; } +function unpackI16(bytes) { return as_signed(bytes[0] << 8 | bytes[1], 16); } + +function packU16(n) { return [(n >> 8) & 0xff, n & 0xff]; } +function unpackU16(bytes) { return as_unsigned(bytes[0] << 8 | bytes[1], 16); } + +function packI32(n) { return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]; } +function unpackI32(bytes) { return as_signed(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3], 32); } + +function packU32(n) { return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]; } +function unpackU32(bytes) { return as_unsigned(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3], 32); } + +function packIEEE754(v, ebits, fbits) { + + var bias = (1 << (ebits - 1)) - 1, + s, e, f, ln, + i, bits, str, bytes; + + function roundToEven(n) { + var w = floor(n), f = n - w; + if (f < 0.5) + return w; + if (f > 0.5) + return w + 1; + return w % 2 ? w + 1 : w; + } + + // Compute sign, exponent, fraction + if (v !== v) { + // NaN + // http://dev.w3.org/2006/webapi/WebIDL/#es-type-mapping + e = (1 << ebits) - 1; f = pow(2, fbits - 1); s = 0; + } else if (v === Infinity || v === -Infinity) { + e = (1 << ebits) - 1; f = 0; s = (v < 0) ? 1 : 0; + } else if (v === 0) { + e = 0; f = 0; s = (1 / v === -Infinity) ? 1 : 0; + } else { + s = v < 0; + v = abs(v); + + if (v >= pow(2, 1 - bias)) { + e = min(floor(log(v) / LN2), 1023); + f = roundToEven(v / pow(2, e) * pow(2, fbits)); + if (f / pow(2, fbits) >= 2) { + e = e + 1; + f = 1; + } + if (e > bias) { + // Overflow + e = (1 << ebits) - 1; + f = 0; + } else { + // Normalized + e = e + bias; + f = f - pow(2, fbits); + } + } else { + // Denormalized + e = 0; + f = roundToEven(v / pow(2, 1 - bias - fbits)); + } + } + + // Pack sign, exponent, fraction + bits = []; + for (i = fbits; i; i -= 1) { bits.push(f % 2 ? 1 : 0); f = floor(f / 2); } + for (i = ebits; i; i -= 1) { bits.push(e % 2 ? 1 : 0); e = floor(e / 2); } + bits.push(s ? 1 : 0); + bits.reverse(); + str = bits.join(''); + + // Bits to bytes + bytes = []; + while (str.length) { + bytes.push(parseInt(str.substring(0, 8), 2)); + str = str.substring(8); + } + return bytes; +} + +function unpackIEEE754(bytes, ebits, fbits) { + + // Bytes to bits + var bits = [], i, j, b, str, + bias, s, e, f; + + for (i = bytes.length; i; i -= 1) { + b = bytes[i - 1]; + for (j = 8; j; j -= 1) { + bits.push(b % 2 ? 1 : 0); b = b >> 1; + } + } + bits.reverse(); + str = bits.join(''); + + // Unpack sign, exponent, fraction + bias = (1 << (ebits - 1)) - 1; + s = parseInt(str.substring(0, 1), 2) ? -1 : 1; + e = parseInt(str.substring(1, 1 + ebits), 2); + f = parseInt(str.substring(1 + ebits), 2); + + // Produce number + if (e === (1 << ebits) - 1) { + return f !== 0 ? NaN : s * Infinity; + } else if (e > 0) { + // Normalized + return s * pow(2, e - bias) * (1 + f / pow(2, fbits)); + } else if (f !== 0) { + // Denormalized + return s * pow(2, -(bias - 1)) * (f / pow(2, fbits)); + } else { + return s < 0 ? -0 : 0; + } +} + +function unpackF64(b) { return unpackIEEE754(b, 11, 52); } +function packF64(v) { return packIEEE754(v, 11, 52); } +function unpackF32(b) { return unpackIEEE754(b, 8, 23); } +function packF32(v) { return packIEEE754(v, 8, 23); } + + +// +// 3 The ArrayBuffer Type +// + +(function() { + + /** @constructor */ + var ArrayBuffer = function ArrayBuffer(length) { + length = ECMAScript.ToInt32(length); + if (length < 0) throw new RangeError('ArrayBuffer size is not a small enough positive integer'); + + this.byteLength = length; + this._bytes = []; + this._bytes.length = length; + + var i; + for (i = 0; i < this.byteLength; i += 1) { + this._bytes[i] = 0; + } + + configureProperties(this); + }; + + exports.ArrayBuffer = exports.ArrayBuffer || ArrayBuffer; + + // + // 4 The ArrayBufferView Type + // + + // NOTE: this constructor is not exported + /** @constructor */ + var ArrayBufferView = function ArrayBufferView() { + //this.buffer = null; + //this.byteOffset = 0; + //this.byteLength = 0; + }; + + // + // 5 The Typed Array View Types + // + + function makeConstructor(bytesPerElement, pack, unpack) { + // Each TypedArray type requires a distinct constructor instance with + // identical logic, which this produces. + + var ctor; + ctor = function(buffer, byteOffset, length) { + var array, sequence, i, s; + + if (!arguments.length || typeof arguments[0] === 'number') { + // Constructor(unsigned long length) + this.length = ECMAScript.ToInt32(arguments[0]); + if (length < 0) throw new RangeError('ArrayBufferView size is not a small enough positive integer'); + + this.byteLength = this.length * this.BYTES_PER_ELEMENT; + this.buffer = new ArrayBuffer(this.byteLength); + this.byteOffset = 0; + } else if (typeof arguments[0] === 'object' && arguments[0].constructor === ctor) { + // Constructor(TypedArray array) + array = arguments[0]; + + this.length = array.length; + this.byteLength = this.length * this.BYTES_PER_ELEMENT; + this.buffer = new ArrayBuffer(this.byteLength); + this.byteOffset = 0; + + for (i = 0; i < this.length; i += 1) { + this._setter(i, array._getter(i)); + } + } else if (typeof arguments[0] === 'object' && + !(arguments[0] instanceof ArrayBuffer || ECMAScript.Class(arguments[0]) === 'ArrayBuffer')) { + // Constructor(sequence<type> array) + sequence = arguments[0]; + + this.length = ECMAScript.ToUint32(sequence.length); + this.byteLength = this.length * this.BYTES_PER_ELEMENT; + this.buffer = new ArrayBuffer(this.byteLength); + this.byteOffset = 0; + + for (i = 0; i < this.length; i += 1) { + s = sequence[i]; + this._setter(i, Number(s)); + } + } else if (typeof arguments[0] === 'object' && + (arguments[0] instanceof ArrayBuffer || ECMAScript.Class(arguments[0]) === 'ArrayBuffer')) { + // Constructor(ArrayBuffer buffer, + // optional unsigned long byteOffset, optional unsigned long length) + this.buffer = buffer; + + this.byteOffset = ECMAScript.ToUint32(byteOffset); + if (this.byteOffset > this.buffer.byteLength) { + throw new RangeError("byteOffset out of range"); + } + + if (this.byteOffset % this.BYTES_PER_ELEMENT) { + // The given byteOffset must be a multiple of the element + // size of the specific type, otherwise an exception is raised. + throw new RangeError("ArrayBuffer length minus the byteOffset is not a multiple of the element size."); + } + + if (arguments.length < 3) { + this.byteLength = this.buffer.byteLength - this.byteOffset; + + if (this.byteLength % this.BYTES_PER_ELEMENT) { + throw new RangeError("length of buffer minus byteOffset not a multiple of the element size"); + } + this.length = this.byteLength / this.BYTES_PER_ELEMENT; + } else { + this.length = ECMAScript.ToUint32(length); + this.byteLength = this.length * this.BYTES_PER_ELEMENT; + } + + if ((this.byteOffset + this.byteLength) > this.buffer.byteLength) { + throw new RangeError("byteOffset and length reference an area beyond the end of the buffer"); + } + } else { + throw new TypeError("Unexpected argument type(s)"); + } + + this.constructor = ctor; + + configureProperties(this); + makeArrayAccessors(this); + }; + + ctor.prototype = new ArrayBufferView(); + ctor.prototype.BYTES_PER_ELEMENT = bytesPerElement; + ctor.prototype._pack = pack; + ctor.prototype._unpack = unpack; + ctor.BYTES_PER_ELEMENT = bytesPerElement; + + // getter type (unsigned long index); + ctor.prototype._getter = function(index) { + if (arguments.length < 1) throw new SyntaxError("Not enough arguments"); + + index = ECMAScript.ToUint32(index); + if (index >= this.length) { + return undefined; + } + + var bytes = [], i, o; + for (i = 0, o = this.byteOffset + index * this.BYTES_PER_ELEMENT; + i < this.BYTES_PER_ELEMENT; + i += 1, o += 1) { + bytes.push(this.buffer._bytes[o]); + } + return this._unpack(bytes); + }; + + // NONSTANDARD: convenience alias for getter: type get(unsigned long index); + ctor.prototype.get = ctor.prototype._getter; + + // setter void (unsigned long index, type value); + ctor.prototype._setter = function(index, value) { + if (arguments.length < 2) throw new SyntaxError("Not enough arguments"); + + index = ECMAScript.ToUint32(index); + if (index >= this.length) { + return undefined; + } + + var bytes = this._pack(value), i, o; + for (i = 0, o = this.byteOffset + index * this.BYTES_PER_ELEMENT; + i < this.BYTES_PER_ELEMENT; + i += 1, o += 1) { + this.buffer._bytes[o] = bytes[i]; + } + }; + + // void set(TypedArray array, optional unsigned long offset); + // void set(sequence<type> array, optional unsigned long offset); + ctor.prototype.set = function(index, value) { + if (arguments.length < 1) throw new SyntaxError("Not enough arguments"); + var array, sequence, offset, len, + i, s, d, + byteOffset, byteLength, tmp; + + if (typeof arguments[0] === 'object' && arguments[0].constructor === this.constructor) { + // void set(TypedArray array, optional unsigned long offset); + array = arguments[0]; + offset = ECMAScript.ToUint32(arguments[1]); + + if (offset + array.length > this.length) { + throw new RangeError("Offset plus length of array is out of range"); + } + + byteOffset = this.byteOffset + offset * this.BYTES_PER_ELEMENT; + byteLength = array.length * this.BYTES_PER_ELEMENT; + + if (array.buffer === this.buffer) { + tmp = []; + for (i = 0, s = array.byteOffset; i < byteLength; i += 1, s += 1) { + tmp[i] = array.buffer._bytes[s]; + } + for (i = 0, d = byteOffset; i < byteLength; i += 1, d += 1) { + this.buffer._bytes[d] = tmp[i]; + } + } else { + for (i = 0, s = array.byteOffset, d = byteOffset; + i < byteLength; i += 1, s += 1, d += 1) { + this.buffer._bytes[d] = array.buffer._bytes[s]; + } + } + } else if (typeof arguments[0] === 'object' && typeof arguments[0].length !== 'undefined') { + // void set(sequence<type> array, optional unsigned long offset); + sequence = arguments[0]; + len = ECMAScript.ToUint32(sequence.length); + offset = ECMAScript.ToUint32(arguments[1]); + + if (offset + len > this.length) { + throw new RangeError("Offset plus length of array is out of range"); + } + + for (i = 0; i < len; i += 1) { + s = sequence[i]; + this._setter(offset + i, Number(s)); + } + } else { + throw new TypeError("Unexpected argument type(s)"); + } + }; + + // TypedArray subarray(long begin, optional long end); + ctor.prototype.subarray = function(start, end) { + function clamp(v, min, max) { return v < min ? min : v > max ? max : v; } + + start = ECMAScript.ToInt32(start); + end = ECMAScript.ToInt32(end); + + if (arguments.length < 1) { start = 0; } + if (arguments.length < 2) { end = this.length; } + + if (start < 0) { start = this.length + start; } + if (end < 0) { end = this.length + end; } + + start = clamp(start, 0, this.length); + end = clamp(end, 0, this.length); + + var len = end - start; + if (len < 0) { + len = 0; + } + + return new this.constructor( + this.buffer, this.byteOffset + start * this.BYTES_PER_ELEMENT, len); + }; + + return ctor; + } + + var Int8Array = makeConstructor(1, packI8, unpackI8); + var Uint8Array = makeConstructor(1, packU8, unpackU8); + var Uint8ClampedArray = makeConstructor(1, packU8Clamped, unpackU8); + var Int16Array = makeConstructor(2, packI16, unpackI16); + var Uint16Array = makeConstructor(2, packU16, unpackU16); + var Int32Array = makeConstructor(4, packI32, unpackI32); + var Uint32Array = makeConstructor(4, packU32, unpackU32); + var Float32Array = makeConstructor(4, packF32, unpackF32); + var Float64Array = makeConstructor(8, packF64, unpackF64); + + exports.Int8Array = exports.Int8Array || Int8Array; + exports.Uint8Array = exports.Uint8Array || Uint8Array; + exports.Uint8ClampedArray = exports.Uint8ClampedArray || Uint8ClampedArray; + exports.Int16Array = exports.Int16Array || Int16Array; + exports.Uint16Array = exports.Uint16Array || Uint16Array; + exports.Int32Array = exports.Int32Array || Int32Array; + exports.Uint32Array = exports.Uint32Array || Uint32Array; + exports.Float32Array = exports.Float32Array || Float32Array; + exports.Float64Array = exports.Float64Array || Float64Array; +}()); + +// +// 6 The DataView View Type +// + +(function() { + function r(array, index) { + return ECMAScript.IsCallable(array.get) ? array.get(index) : array[index]; + } + + var IS_BIG_ENDIAN = (function() { + var u16array = new(exports.Uint16Array)([0x1234]), + u8array = new(exports.Uint8Array)(u16array.buffer); + return r(u8array, 0) === 0x12; + }()); + + // Constructor(ArrayBuffer buffer, + // optional unsigned long byteOffset, + // optional unsigned long byteLength) + /** @constructor */ + var DataView = function DataView(buffer, byteOffset, byteLength) { + if (arguments.length === 0) { + buffer = new exports.ArrayBuffer(0); + } else if (!(buffer instanceof exports.ArrayBuffer || ECMAScript.Class(buffer) === 'ArrayBuffer')) { + throw new TypeError("TypeError"); + } + + this.buffer = buffer || new exports.ArrayBuffer(0); + + this.byteOffset = ECMAScript.ToUint32(byteOffset); + if (this.byteOffset > this.buffer.byteLength) { + throw new RangeError("byteOffset out of range"); + } + + if (arguments.length < 3) { + this.byteLength = this.buffer.byteLength - this.byteOffset; + } else { + this.byteLength = ECMAScript.ToUint32(byteLength); + } + + if ((this.byteOffset + this.byteLength) > this.buffer.byteLength) { + throw new RangeError("byteOffset and length reference an area beyond the end of the buffer"); + } + + configureProperties(this); + }; + + function makeGetter(arrayType) { + return function(byteOffset, littleEndian) { + + byteOffset = ECMAScript.ToUint32(byteOffset); + + if (byteOffset + arrayType.BYTES_PER_ELEMENT > this.byteLength) { + throw new RangeError("Array index out of range"); + } + byteOffset += this.byteOffset; + + var uint8Array = new exports.Uint8Array(this.buffer, byteOffset, arrayType.BYTES_PER_ELEMENT), + bytes = [], i; + for (i = 0; i < arrayType.BYTES_PER_ELEMENT; i += 1) { + bytes.push(r(uint8Array, i)); + } + + if (Boolean(littleEndian) === Boolean(IS_BIG_ENDIAN)) { + bytes.reverse(); + } + + return r(new arrayType(new exports.Uint8Array(bytes).buffer), 0); + }; + } + + DataView.prototype.getUint8 = makeGetter(exports.Uint8Array); + DataView.prototype.getInt8 = makeGetter(exports.Int8Array); + DataView.prototype.getUint16 = makeGetter(exports.Uint16Array); + DataView.prototype.getInt16 = makeGetter(exports.Int16Array); + DataView.prototype.getUint32 = makeGetter(exports.Uint32Array); + DataView.prototype.getInt32 = makeGetter(exports.Int32Array); + DataView.prototype.getFloat32 = makeGetter(exports.Float32Array); + DataView.prototype.getFloat64 = makeGetter(exports.Float64Array); + + function makeSetter(arrayType) { + return function(byteOffset, value, littleEndian) { + + byteOffset = ECMAScript.ToUint32(byteOffset); + if (byteOffset + arrayType.BYTES_PER_ELEMENT > this.byteLength) { + throw new RangeError("Array index out of range"); + } + + // Get bytes + var typeArray = new arrayType([value]), + byteArray = new exports.Uint8Array(typeArray.buffer), + bytes = [], i, byteView; + + for (i = 0; i < arrayType.BYTES_PER_ELEMENT; i += 1) { + bytes.push(r(byteArray, i)); + } + + // Flip if necessary + if (Boolean(littleEndian) === Boolean(IS_BIG_ENDIAN)) { + bytes.reverse(); + } + + // Write them + byteView = new exports.Uint8Array(this.buffer, byteOffset, arrayType.BYTES_PER_ELEMENT); + byteView.set(bytes); + }; + } + + DataView.prototype.setUint8 = makeSetter(exports.Uint8Array); + DataView.prototype.setInt8 = makeSetter(exports.Int8Array); + DataView.prototype.setUint16 = makeSetter(exports.Uint16Array); + DataView.prototype.setInt16 = makeSetter(exports.Int16Array); + DataView.prototype.setUint32 = makeSetter(exports.Uint32Array); + DataView.prototype.setInt32 = makeSetter(exports.Int32Array); + DataView.prototype.setFloat32 = makeSetter(exports.Float32Array); + DataView.prototype.setFloat64 = makeSetter(exports.Float64Array); + + exports.DataView = exports.DataView || DataView; + +}());
@@ -0,0 +1,79 @@
+{ + "name": "typedarray", + "version": "0.0.6", + "description": "TypedArray polyfill for old browsers", + "main": "index.js", + "devDependencies": { + "tape": "~2.3.2" + }, + "scripts": { + "test": "tape test/*.js test/server/*.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/substack/typedarray.git" + }, + "homepage": "https://github.com/substack/typedarray", + "keywords": [ + "ArrayBuffer", + "DataView", + "Float32Array", + "Float64Array", + "Int8Array", + "Int16Array", + "Int32Array", + "Uint8Array", + "Uint8ClampedArray", + "Uint16Array", + "Uint32Array", + "typed", + "array", + "polyfill" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "license": "MIT", + "testling": { + "files": "test/*.js", + "browsers": [ + "ie/6..latest", + "firefox/16..latest", + "firefox/nightly", + "chrome/22..latest", + "chrome/canary", + "opera/12..latest", + "opera/next", + "safari/5.1..latest", + "ipad/6.0..latest", + "iphone/6.0..latest", + "android-browser/4.2..latest" + ] + }, + "bugs": { + "url": "https://github.com/substack/typedarray/issues" + }, + "_id": "typedarray@0.0.6", + "dist": { + "shasum": "867ac74e3864187b1d3d47d996a78ec5c8830777", + "tarball": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" + }, + "_from": "typedarray@>=0.0.5 <0.1.0", + "_npmVersion": "1.4.3", + "_npmUser": { + "name": "substack", + "email": "mail@substack.net" + }, + "maintainers": [ + { + "name": "substack", + "email": "mail@substack.net" + } + ], + "directories": {}, + "_shasum": "867ac74e3864187b1d3d47d996a78ec5c8830777", + "_resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,61 @@
+# typedarray + +TypedArray polyfill ripped from [this +module](https://raw.github.com/inexorabletash/polyfill). + +[](http://travis-ci.org/substack/typedarray) + +[](https://ci.testling.com/substack/typedarray) + +# example + +``` js +var Uint8Array = require('typedarray').Uint8Array; +var ua = new Uint8Array(5); +ua[1] = 256 + 55; +console.log(ua[1]); +``` + +output: + +``` +55 +``` + +# methods + +``` js +var TA = require('typedarray') +``` + +The `TA` object has the following constructors: + +* TA.ArrayBuffer +* TA.DataView +* TA.Float32Array +* TA.Float64Array +* TA.Int8Array +* TA.Int16Array +* TA.Int32Array +* TA.Uint8Array +* TA.Uint8ClampedArray +* TA.Uint16Array +* TA.Uint32Array + +# install + +With [npm](https://npmjs.org) do: + +``` +npm install typedarray +``` + +To use this module in the browser, compile with +[browserify](http://browserify.org) +or download a UMD build from browserify CDN: + +http://wzrd.in/standalone/typedarray@latest + +# license + +MIT
@@ -0,0 +1,19 @@
+var test = require('tape'); +var vm = require('vm'); +var fs = require('fs'); +var src = fs.readFileSync(__dirname + '/../../index.js', 'utf8'); + +test('u8a without globals', function (t) { + var c = { + module: { exports: {} }, + }; + c.exports = c.module.exports; + vm.runInNewContext(src, c); + var TA = c.module.exports; + var ua = new(TA.Uint8Array)(5); + + t.equal(ua.length, 5); + ua[1] = 256 + 55; + t.equal(ua[1], 55); + t.end(); +});
@@ -0,0 +1,10 @@
+var TA = require('../'); +var test = require('tape'); + +test('tiny u8a test', function (t) { + var ua = new(TA.Uint8Array)(5); + t.equal(ua.length, 5); + ua[1] = 256 + 55; + t.equal(ua[1], 55); + t.end(); +});
@@ -0,0 +1,81 @@
+{ + "name": "concat-stream", + "version": "1.4.10", + "description": "writable stream that concatenates strings or binary data and calls a callback with the result", + "tags": [ + "stream", + "simple", + "util", + "utility" + ], + "author": { + "name": "Max Ogden", + "email": "max@maxogden.com" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/maxogden/concat-stream.git" + }, + "bugs": { + "url": "http://github.com/maxogden/concat-stream/issues" + }, + "engines": [ + "node >= 0.8" + ], + "main": "index.js", + "files": [ + "index.js" + ], + "scripts": { + "test": "tape test/*.js test/server/*.js" + }, + "license": "MIT", + "dependencies": { + "inherits": "~2.0.1", + "typedarray": "~0.0.5", + "readable-stream": "~1.1.9" + }, + "devDependencies": { + "tape": "~2.3.2" + }, + "testling": { + "files": "test/*.js", + "browsers": [ + "ie/8..latest", + "firefox/17..latest", + "firefox/nightly", + "chrome/22..latest", + "chrome/canary", + "opera/12..latest", + "opera/next", + "safari/5.1..latest", + "ipad/6.0..latest", + "iphone/6.0..latest", + "android-browser/4.2..latest" + ] + }, + "gitHead": "71d37be263a0457b8afcbb27237e71ddca634373", + "homepage": "https://github.com/maxogden/concat-stream#readme", + "_id": "concat-stream@1.4.10", + "_shasum": "acc3bbf5602cb8cc980c6ac840fa7d8603e3ef36", + "_from": "concat-stream@>=1.4.7 <1.5.0", + "_npmVersion": "2.9.0", + "_nodeVersion": "1.8.2", + "_npmUser": { + "name": "maxogden", + "email": "max@maxogden.com" + }, + "maintainers": [ + { + "name": "maxogden", + "email": "max@maxogden.com" + } + ], + "dist": { + "shasum": "acc3bbf5602cb8cc980c6ac840fa7d8603e3ef36", + "tarball": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.4.10.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.4.10.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,94 @@
+# concat-stream + +Writable stream that concatenates strings or binary data and calls a callback with the result. Not a transform stream -- more of a stream sink. + +[](https://travis-ci.org/maxogden/concat-stream) + +[](https://nodei.co/npm/concat-stream/) + +### description + +Streams emit many buffers. If you want to collect all of the buffers, and when the stream ends concatenate all of the buffers together and receive a single buffer then this is the module for you. + +Only use this if you know you can fit all of the output of your stream into a single Buffer (e.g. in RAM). + +There are also `objectMode` streams that emit things other than Buffers, and you can concatenate these too. See below for details. + +### examples + +#### Buffers + +```js +var fs = require('fs') +var concat = require('concat-stream') + +var readStream = fs.createReadStream('cat.png') +var concatStream = concat(gotPicture) + +readStream.on('error', handleError) +readStream.pipe(concatStream) + +function gotPicture(imageBuffer) { + // imageBuffer is all of `cat.png` as a node.js Buffer +} + +function handleError(err) { + // handle your error appropriately here, e.g.: + console.error(err) // print the error to STDERR + process.exit(1) // exit program with non-zero exit code +} + +``` + +#### Arrays + +```js +var write = concat(function(data) {}) +write.write([1,2,3]) +write.write([4,5,6]) +write.end() +// data will be [1,2,3,4,5,6] in the above callback +``` + +#### Uint8Arrays + +```js +var write = concat(function(data) {}) +var a = new Uint8Array(3) +a[0] = 97; a[1] = 98; a[2] = 99 +write.write(a) +write.write('!') +write.end(Buffer('!!1')) +``` + +See `test/` for more examples + +# methods + +```js +var concat = require('concat-stream') +``` + +## var writable = concat(opts={}, cb) + +Return a `writable` stream that will fire `cb(data)` with all of the data that +was written to the stream. Data can be written to `writable` as strings, +Buffers, arrays of byte integers, and Uint8Arrays. + +By default `concat-stream` will give you back the same data type as the type of the first buffer written to the stream. Use `opts.encoding` to set what format `data` should be returned as, e.g. if you if you don't want to rely on the built-in type checking or for some other reason. + +* `string` - get a string +* `buffer` - get back a Buffer +* `array` - get an array of byte integers +* `uint8array`, `u8`, `uint8` - get back a Uint8Array +* `object`, get back an array of Objects + +If you don't specify an encoding, and the types can't be inferred (e.g. you write things that aren't in the list above), it will try to convert concat them into a `Buffer`. + +# error handling + +`concat-stream` does not handle errors for you, so you must handle errors on whatever streams you pipe into `concat-stream`. This is a general rule when programming with node.js streams: always handle errors on each and every stream. Since `concat-stream` is not itself a stream it does not emit errors. + +# license + +MIT LICENSE
@@ -0,0 +1,45 @@
+'use strict'; +var path = require('path'); +var minimist = require('minimist'); +var indentString = require('indent-string'); +var objectAssign = require('object-assign'); +var camelcaseKeys = require('camelcase-keys'); + +// needed to get the uncached parent +delete require.cache[__filename]; +var parentDir = path.dirname(module.parent.filename); + +module.exports = function (opts, minimistOpts) { + opts = objectAssign({ + pkg: './package.json', + argv: process.argv.slice(2) + }, opts); + + var pkg = require(path.join(parentDir, opts.pkg)); + var argv = minimist(opts.argv, minimistOpts); + var help = '\n' + indentString(pkg.description + (opts.help ? '\n\n' + opts.help : '\n'), ' '); + var showHelp = function () { + console.log(help); + process.exit(); + }; + + if (argv.version) { + console.log(pkg.version); + process.exit(); + } + + if (argv.help) { + showHelp(); + } + + var _ = argv._; + delete argv._; + + return { + input: _, + flags: camelcaseKeys(argv), + pkg: pkg, + help: help, + showHelp: showHelp + }; +};
@@ -0,0 +1,1 @@
+../indent-string/cli.js
@@ -0,0 +1,9 @@
+'use strict'; +var mapObj = require('map-obj'); +var camelCase = require('camelcase'); + +module.exports = function (obj) { + return mapObj(obj, function (key, val) { + return [camelCase(key), val]; + }); +};
@@ -0,0 +1,27 @@
+'use strict'; +module.exports = function () { + var str = [].map.call(arguments, function (str) { + return str.trim(); + }).filter(function (str) { + return str.length; + }).join('-'); + + if (!str.length) { + return ''; + } + + if (str.length === 1 || !(/[_.\- ]+/).test(str) ) { + if (str[0] === str[0].toLowerCase() && str.slice(1) !== str.slice(1).toLowerCase()) { + return str; + } + + return str.toLowerCase(); + } + + return str + .replace(/^[_.\- ]+/, '') + .toLowerCase() + .replace(/[_.\- ]+(\w|$)/g, function (m, p1) { + return p1.toUpperCase(); + }); +};
@@ -0,0 +1,21 @@
+The MIT License (MIT) + +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.
@@ -0,0 +1,67 @@
+{ + "name": "camelcase", + "version": "1.2.1", + "description": "Convert a dash/dot/underscore/space separated string to camelCase: foo-bar → fooBar", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/sindresorhus/camelcase" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "http://sindresorhus.com" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "node test.js" + }, + "files": [ + "index.js" + ], + "keywords": [ + "camelcase", + "camel-case", + "camel", + "case", + "dash", + "hyphen", + "dot", + "underscore", + "separator", + "string", + "text", + "convert" + ], + "devDependencies": { + "ava": "0.0.4" + }, + "gitHead": "185ba12da723be9c1ee986cc2956bdc4c517a141", + "bugs": { + "url": "https://github.com/sindresorhus/camelcase/issues" + }, + "homepage": "https://github.com/sindresorhus/camelcase", + "_id": "camelcase@1.2.1", + "_shasum": "9bb5304d2e0b56698b2c758b08a3eaa9daa58a39", + "_from": "camelcase@>=1.0.1 <2.0.0", + "_npmVersion": "2.11.2", + "_nodeVersion": "0.12.5", + "_npmUser": { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + "dist": { + "shasum": "9bb5304d2e0b56698b2c758b08a3eaa9daa58a39", + "tarball": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz" + }, + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz" +}
@@ -0,0 +1,56 @@
+# camelcase [](https://travis-ci.org/sindresorhus/camelcase) + +> Convert a dash/dot/underscore/space separated string to camelCase: `foo-bar` → `fooBar` + + +## Install + +```sh +$ npm install --save camelcase +``` + + +## Usage + +```js +var camelCase = require('camelcase'); + +camelCase('foo-bar'); +//=> fooBar + +camelCase('foo_bar'); +//=> fooBar + +camelCase('Foo-Bar'); +//=> fooBar + +camelCase('--foo.bar'); +//=> fooBar + +camelCase('__foo__bar__'); +//=> fooBar + +camelCase('foo bar'); +//=> fooBar + +console.log(process.argv[3]); +//=> --foo-bar +camelCase(process.argv[3]); +//=> fooBar + +camelCase('foo', 'bar'); +//=> fooBar + +camelCase('__foo__', '--bar'); +//=> fooBar +``` + + +## Related + +See [`decamelize`](https://github.com/sindresorhus/decamelize) for the inverse. + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,13 @@
+'use strict'; +module.exports = function (obj, cb) { + var ret = {}; + var keys = Object.keys(obj); + + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var res = cb(key, obj[key], obj); + ret[res[0]] = res[1]; + } + + return ret; +};
@@ -0,0 +1,21 @@
+The MIT License (MIT) + +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.
@@ -0,0 +1,65 @@
+{ + "name": "map-obj", + "version": "1.0.1", + "description": "Map object keys and values into a new object", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/sindresorhus/map-obj" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "node test.js" + }, + "files": [ + "index.js" + ], + "keywords": [ + "map", + "obj", + "object", + "key", + "keys", + "value", + "values", + "val", + "iterate", + "iterator" + ], + "devDependencies": { + "ava": "0.0.4" + }, + "gitHead": "a4f2d49ae6b5f7c0e55130b49ab0412298b797bc", + "bugs": { + "url": "https://github.com/sindresorhus/map-obj/issues" + }, + "homepage": "https://github.com/sindresorhus/map-obj", + "_id": "map-obj@1.0.1", + "_shasum": "d933ceb9205d82bdcf4886f6742bdc2b4dea146d", + "_from": "map-obj@>=1.0.0 <2.0.0", + "_npmVersion": "2.7.4", + "_nodeVersion": "0.12.2", + "_npmUser": { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + "dist": { + "shasum": "d933ceb9205d82bdcf4886f6742bdc2b4dea146d", + "tarball": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz" + }, + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz" +}
@@ -0,0 +1,29 @@
+# map-obj [](https://travis-ci.org/sindresorhus/map-obj) + +> Map object keys and values into a new object + + +## Install + +``` +$ npm install --save map-obj +``` + + +## Usage + +```js +var mapObj = require('map-obj'); + +var newObject = mapObj({foo: 'bar'}, function (key, value, object) { + // first element is the new key and second is the new value + // here we reverse the order + return [value, key]; +}); +//=> {bar: 'foo'} +``` + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,80 @@
+{ + "name": "camelcase-keys", + "version": "1.0.0", + "description": "Convert object keys to camelCase", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/sindresorhus/camelcase-keys" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "http://sindresorhus.com" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "node test.js" + }, + "files": [ + "index.js" + ], + "keywords": [ + "map", + "obj", + "object", + "key", + "keys", + "value", + "values", + "val", + "iterate", + "camelcase", + "camel-case", + "camel", + "case", + "dash", + "hyphen", + "dot", + "underscore", + "separator", + "string", + "text", + "convert" + ], + "devDependencies": { + "ava": "0.0.4" + }, + "dependencies": { + "camelcase": "^1.0.1", + "map-obj": "^1.0.0" + }, + "gitHead": "fbb9ff793a80f990e8e3c8963ba36e2c14d569d7", + "bugs": { + "url": "https://github.com/sindresorhus/camelcase-keys/issues" + }, + "homepage": "https://github.com/sindresorhus/camelcase-keys", + "_id": "camelcase-keys@1.0.0", + "_shasum": "bd1a11bf9b31a1ce493493a930de1a0baf4ad7ec", + "_from": "camelcase-keys@>=1.0.0 <2.0.0", + "_npmVersion": "2.1.2", + "_nodeVersion": "0.10.32", + "_npmUser": { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + } + ], + "dist": { + "shasum": "bd1a11bf9b31a1ce493493a930de1a0baf4ad7ec", + "tarball": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-1.0.0.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-1.0.0.tgz" +}
@@ -0,0 +1,32 @@
+# camelcase-keys [](https://travis-ci.org/sindresorhus/camelcase-keys) + +> Convert object keys to camelCase using [`camelcase`](https://github.com/sindresorhus/camelcase) + + +## Install + +```sh +$ npm install --save camelcase-keys +``` + + +## Usage + +```js +var camelcaseKeys = require('camelcase-keys'); + +camelcaseKeys({'foo-bar': true}); +//=> {fooBar: true} + + +var argv = require('minimist')(process.argv.slice(2)); +//=> {_: [], 'foo-bar': true} + +camelcaseKeys(argv); +//=> {_: [], fooBar: true} +``` + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,48 @@
+#!/usr/bin/env node +'use strict'; +var stdin = require('get-stdin'); +var argv = require('minimist')(process.argv.slice(2)); +var pkg = require('./package.json'); +var indentString = require('./'); +var input = argv._; + +function help() { + console.log([ + '', + ' ' + pkg.description, + '', + ' Usage', + ' indent-string <string> [--indent <string>] [--count <number>]', + ' cat file.txt | indent-string > indented-file.txt', + '', + ' Example', + ' indent-string "$(printf \'Unicorns\\nRainbows\\n\')" --indent ♥ --count 4', + ' ♥♥♥♥Unicorns', + ' ♥♥♥♥Rainbows' + ].join('\n')); +} + +function init(data) { + console.log(indentString(data, argv.indent || ' ', argv.count)); +} + +if (argv.help) { + help(); + return; +} + +if (argv.version) { + console.log(pkg.version); + return; +} + +if (process.stdin.isTTY) { + if (!input) { + help(); + return; + } + + init(input[0]); +} else { + stdin(init); +}
@@ -0,0 +1,20 @@
+'use strict'; +var repeating = require('repeating'); + +module.exports = function (str, indent, count) { + if (typeof str !== 'string' || typeof indent !== 'string') { + throw new TypeError('`string` and `indent` should be strings'); + } + + if (count != null && typeof count !== 'number') { + throw new TypeError('`count` should be a number'); + } + + if (count === 0) { + return str; + } + + indent = count > 1 ? repeating(indent, count) : indent; + + return str.replace(/^(?!\s*$)/mg, indent); +};
@@ -0,0 +1,21 @@
+The MIT License (MIT) + +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.
@@ -0,0 +1,1 @@
+../repeating/cli.js
@@ -0,0 +1,49 @@
+'use strict'; + +module.exports = function (cb) { + var stdin = process.stdin; + var ret = ''; + + if (stdin.isTTY) { + setImmediate(cb, ''); + return; + } + + stdin.setEncoding('utf8'); + + stdin.on('readable', function () { + var chunk; + + while (chunk = stdin.read()) { + ret += chunk; + } + }); + + stdin.on('end', function () { + cb(ret); + }); +}; + +module.exports.buffer = function (cb) { + var stdin = process.stdin; + var ret = []; + var len = 0; + + if (stdin.isTTY) { + setImmediate(cb, new Buffer('')); + return; + } + + stdin.on('readable', function () { + var chunk; + + while (chunk = stdin.read()) { + ret.push(chunk); + len += chunk.length; + } + }); + + stdin.on('end', function () { + cb(Buffer.concat(ret, len)); + }); +};
@@ -0,0 +1,63 @@
+{ + "name": "get-stdin", + "version": "4.0.1", + "description": "Easier stdin", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/sindresorhus/get-stdin" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "http://sindresorhus.com" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "node test.js && node test-buffer.js && echo unicorns | node test-real.js" + }, + "files": [ + "index.js" + ], + "keywords": [ + "std", + "stdin", + "stdio", + "concat", + "buffer", + "stream", + "process", + "stream" + ], + "devDependencies": { + "ava": "0.0.4", + "buffer-equal": "0.0.1" + }, + "gitHead": "65c744975229b25d6cc5c7546f49b6ad9099553f", + "bugs": { + "url": "https://github.com/sindresorhus/get-stdin/issues" + }, + "homepage": "https://github.com/sindresorhus/get-stdin", + "_id": "get-stdin@4.0.1", + "_shasum": "b968c6b0a04384324902e8bf1a5df32579a450fe", + "_from": "get-stdin@>=4.0.1 <5.0.0", + "_npmVersion": "1.4.28", + "_npmUser": { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + } + ], + "dist": { + "shasum": "b968c6b0a04384324902e8bf1a5df32579a450fe", + "tarball": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" +}
@@ -0,0 +1,44 @@
+# get-stdin [](https://travis-ci.org/sindresorhus/get-stdin) + +> Easier stdin + + +## Install + +```sh +$ npm install --save get-stdin +``` + + +## Usage + +```js +// example.js +var stdin = require('get-stdin'); + +stdin(function (data) { + console.log(data); + //=> unicorns +}); +``` + +```sh +$ echo unicorns | node example.js +unicorns +``` + + +## API + +### stdin(callback) + +Get `stdin` as a string. + +### stdin.buffer(callback) + +Get `stdin` as a buffer. + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,36 @@
+#!/usr/bin/env node +'use strict'; +var pkg = require('./package.json'); +var repeating = require('./'); +var argv = process.argv.slice(2); + +function help() { + console.log([ + '', + ' ' + pkg.description, + '', + ' Usage', + ' $ repeating <string> <count>', + '', + ' Example', + ' $ repeating \'unicorn \' 2', + ' unicorn unicorn' + ].join('\n')); +} + +if (process.argv.indexOf('--help') !== -1) { + help(); + return; +} + +if (process.argv.indexOf('--version') !== -1) { + console.log(pkg.version); + return; +} + +if (!argv[1]) { + console.error('You have to define how many times to repeat the string.'); + process.exit(1); +} + +console.log(repeating(argv[0], Number(argv[1])));
@@ -0,0 +1,24 @@
+'use strict'; +var isFinite = require('is-finite'); + +module.exports = function (str, n) { + if (typeof str !== 'string') { + throw new TypeError('Expected a string as the first argument'); + } + + if (n < 0 || !isFinite(n)) { + throw new TypeError('Expected a finite positive number'); + } + + var ret = ''; + + do { + if (n & 1) { + ret += str; + } + + str += str; + } while (n = n >> 1); + + return ret; +};
@@ -0,0 +1,21 @@
+The MIT License (MIT) + +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.
@@ -0,0 +1,6 @@
+'use strict'; +var numberIsNan = require('number-is-nan'); + +module.exports = Number.isFinite || function (val) { + return !(typeof val !== 'number' || numberIsNan(val) || val === Infinity || val === -Infinity); +};
@@ -0,0 +1,21 @@
+The MIT License (MIT) + +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.
@@ -0,0 +1,4 @@
+'use strict'; +module.exports = Number.isNaN || function (x) { + return x !== x; +};
@@ -0,0 +1,21 @@
+The MIT License (MIT) + +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.
@@ -0,0 +1,67 @@
+{ + "name": "number-is-nan", + "version": "1.0.0", + "description": "ES6 Number.isNaN() ponyfill", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/number-is-nan.git" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "node test.js" + }, + "files": [ + "index.js" + ], + "keywords": [ + "es6", + "es2015", + "ecmascript", + "harmony", + "ponyfill", + "polyfill", + "shim", + "number", + "is", + "nan", + "not" + ], + "devDependencies": { + "ava": "0.0.4" + }, + "gitHead": "0f394b1bc33185c40304363b209e3f0588dbeeb3", + "bugs": { + "url": "https://github.com/sindresorhus/number-is-nan/issues" + }, + "homepage": "https://github.com/sindresorhus/number-is-nan#readme", + "_id": "number-is-nan@1.0.0", + "_shasum": "c020f529c5282adfdd233d91d4b181c3d686dc4b", + "_from": "number-is-nan@>=1.0.0 <2.0.0", + "_npmVersion": "2.10.0", + "_nodeVersion": "0.12.3", + "_npmUser": { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + "dist": { + "shasum": "c020f529c5282adfdd233d91d4b181c3d686dc4b", + "tarball": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz" + }, + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,30 @@
+# number-is-nan [](https://travis-ci.org/sindresorhus/number-is-nan) + +> ES6 [`Number.isNaN()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN) ponyfill + +> Ponyfill: A polyfill that doesn't overwrite the native method + + +## Install + +``` +$ npm install --save number-is-nan +``` + + +## Usage + +```js +var numberIsNan = require('number-is-nan'); + +numberIsNan(NaN); +//=> true + +numberIsNan('unicorn'); +//=> false +``` + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,68 @@
+{ + "name": "is-finite", + "version": "1.0.1", + "description": "ES6 Number.isFinite() ponyfill", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/is-finite.git" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "node test.js" + }, + "files": [ + "index.js" + ], + "keywords": [ + "es6", + "ecmascript", + "harmony", + "ponyfill", + "polyfill", + "shim", + "number", + "finite", + "is" + ], + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "devDependencies": { + "ava": "0.0.4" + }, + "gitHead": "7d952746a66df2f9955a59a0d013ed14b3ad1f60", + "bugs": { + "url": "https://github.com/sindresorhus/is-finite/issues" + }, + "homepage": "https://github.com/sindresorhus/is-finite#readme", + "_id": "is-finite@1.0.1", + "_shasum": "6438603eaebe2793948ff4a4262ec8db3d62597b", + "_from": "is-finite@>=1.0.0 <2.0.0", + "_npmVersion": "2.10.0", + "_nodeVersion": "0.12.3", + "_npmUser": { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + "dist": { + "shasum": "6438603eaebe2793948ff4a4262ec8db3d62597b", + "tarball": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.1.tgz" + }, + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.1.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,30 @@
+# is-finite [](https://travis-ci.org/sindresorhus/is-finite) + +> ES6 [`Number.isFinite()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite) ponyfill + +> Ponyfill: A polyfill that doesn't overwrite the native method + + +## Install + +```sh +$ npm install --save is-finite +``` + + +## Usage + +```js +var numIsFinite = require('is-finite'); + +numIsFinite(4); +//=> true + +numIsFinite(Infinity); +//=> false +``` + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,72 @@
+{ + "name": "repeating", + "version": "1.1.3", + "description": "Repeat a string - fast", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/sindresorhus/repeating.git" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "bin": { + "repeating": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "node test.js" + }, + "files": [ + "index.js", + "cli.js" + ], + "keywords": [ + "cli-app", + "cli", + "bin", + "repeat", + "repeating", + "string", + "str", + "text", + "fill" + ], + "dependencies": { + "is-finite": "^1.0.0" + }, + "devDependencies": { + "ava": "0.0.4" + }, + "gitHead": "23e93be864952600940d29c8d67f2b9a09d48d81", + "bugs": { + "url": "https://github.com/sindresorhus/repeating/issues" + }, + "homepage": "https://github.com/sindresorhus/repeating", + "_id": "repeating@1.1.3", + "_shasum": "3d4114218877537494f97f77f9785fab810fa4ac", + "_from": "repeating@>=1.1.0 <2.0.0", + "_npmVersion": "2.10.1", + "_nodeVersion": "0.12.4", + "_npmUser": { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + "dist": { + "shasum": "3d4114218877537494f97f77f9785fab810fa4ac", + "tarball": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz" + }, + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,40 @@
+# repeating [](https://travis-ci.org/sindresorhus/repeating) + +> Repeat a string - fast + + +## Usage + +```sh +$ npm install --save repeating +``` + +```js +var repeating = require('repeating'); + +repeating('unicorn ', 100); +//=> unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn unicorn +``` + + +## CLI + +```sh +$ npm install --global repeating +``` + +``` +$ repeating --help + + Usage + repeating <string> <count> + + Example + repeating 'unicorn ' 2 + unicorn unicorn +``` + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,72 @@
+{ + "name": "indent-string", + "version": "1.2.2", + "description": "Indent each line in a string", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/sindresorhus/indent-string" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "bin": { + "indent-string": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "mocha" + }, + "files": [ + "index.js", + "cli.js" + ], + "keywords": [ + "cli-app", + "cli", + "bin", + "indent", + "string", + "str", + "pad", + "line" + ], + "dependencies": { + "get-stdin": "^4.0.1", + "minimist": "^1.1.0", + "repeating": "^1.1.0" + }, + "devDependencies": { + "mocha": "*" + }, + "gitHead": "ce73faa67c3573fa81bf88796b8f4915ba09593e", + "bugs": { + "url": "https://github.com/sindresorhus/indent-string/issues" + }, + "homepage": "https://github.com/sindresorhus/indent-string", + "_id": "indent-string@1.2.2", + "_shasum": "db99bcc583eb6abbb1e48dcbb1999a986041cb6b", + "_from": "indent-string@>=1.1.0 <2.0.0", + "_npmVersion": "2.11.2", + "_nodeVersion": "0.12.5", + "_npmUser": { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + "dist": { + "shasum": "db99bcc583eb6abbb1e48dcbb1999a986041cb6b", + "tarball": "https://registry.npmjs.org/indent-string/-/indent-string-1.2.2.tgz" + }, + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/indent-string/-/indent-string-1.2.2.tgz" +}
@@ -0,0 +1,77 @@
+# indent-string [](https://travis-ci.org/sindresorhus/indent-string) + +> Indent each line in a string + + +## Install + +```sh +$ npm install --save indent-string +``` + + +## Usage + +```js +var indentString = require('indent-string'); + +indentString('Unicorns\nRainbows', '♥', 4); +//=> ♥♥♥♥Unicorns +//=> ♥♥♥♥Rainbows +``` + + +## API + +### indentString(string, indent, count) + +#### string + +**Required** +Type: `string` + +The string you want to indent. + +#### indent + +**Required** +Type: `string` + +The string to use for the indent. + +#### count + +Type: `number` +Default: `1` + +How many times you want `indent` repeated. + + +## CLI + +```sh +$ npm install --global indent-string +``` + +```sh +$ indent-string --help + + Usage + indent-string <string> [--indent <string>] [--count <number>] + cat file.txt | indent-string > indented-file.txt + + Example + indent-string "$(printf 'Unicorns\nRainbows\n')" --indent ♥ --count 4 + ♥♥♥♥Unicorns + ♥♥♥♥Rainbows +``` + + +## Related + +- [strip-indent](https://github.com/sindresorhus/strip-indent) - Strip leading whitespace from every line in a string + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,8 @@
+language: node_js +node_js: + - "0.8" + - "0.10" + - "0.12" + - "iojs" +before_install: + - npm install -g npm@~1.4.6
@@ -0,0 +1,18 @@
+This software is released under the MIT license: + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,2 @@
+var argv = require('../')(process.argv.slice(2)); +console.dir(argv);
@@ -0,0 +1,236 @@
+module.exports = function (args, opts) { + if (!opts) opts = {}; + + var flags = { bools : {}, strings : {}, unknownFn: null }; + + if (typeof opts['unknown'] === 'function') { + flags.unknownFn = opts['unknown']; + } + + if (typeof opts['boolean'] === 'boolean' && opts['boolean']) { + flags.allBools = true; + } else { + [].concat(opts['boolean']).filter(Boolean).forEach(function (key) { + flags.bools[key] = true; + }); + } + + var aliases = {}; + Object.keys(opts.alias || {}).forEach(function (key) { + aliases[key] = [].concat(opts.alias[key]); + aliases[key].forEach(function (x) { + aliases[x] = [key].concat(aliases[key].filter(function (y) { + return x !== y; + })); + }); + }); + + [].concat(opts.string).filter(Boolean).forEach(function (key) { + flags.strings[key] = true; + if (aliases[key]) { + flags.strings[aliases[key]] = true; + } + }); + + var defaults = opts['default'] || {}; + + var argv = { _ : [] }; + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] === undefined ? false : defaults[key]); + }); + + var notFlags = []; + + if (args.indexOf('--') !== -1) { + notFlags = args.slice(args.indexOf('--')+1); + args = args.slice(0, args.indexOf('--')); + } + + function argDefined(key, arg) { + return (flags.allBools && /^--[^=]+$/.test(arg)) || + flags.strings[key] || flags.bools[key] || aliases[key]; + } + + function setArg (key, val, arg) { + if (arg && flags.unknownFn && !argDefined(key, arg)) { + if (flags.unknownFn(arg) === false) return; + } + + var value = !flags.strings[key] && isNumber(val) + ? Number(val) : val + ; + setKey(argv, key.split('.'), value); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), value); + }); + } + + function setKey (obj, keys, value) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + if (o[key] === undefined) o[key] = {}; + o = o[key]; + }); + + var key = keys[keys.length - 1]; + if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') { + o[key] = value; + } + else if (Array.isArray(o[key])) { + o[key].push(value); + } + else { + o[key] = [ o[key], value ]; + } + } + + function aliasIsBoolean(key) { + return aliases[key].some(function (x) { + return flags.bools[x]; + }); + } + + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + + if (/^--.+=/.test(arg)) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + var m = arg.match(/^--([^=]+)=([\s\S]*)$/); + var key = m[1]; + var value = m[2]; + if (flags.bools[key]) { + value = value !== 'false'; + } + setArg(key, value, arg); + } + else if (/^--no-.+/.test(arg)) { + var key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false, arg); + } + else if (/^--.+/.test(arg)) { + var key = arg.match(/^--(.+)/)[1]; + var next = args[i + 1]; + if (next !== undefined && !/^-/.test(next) + && !flags.bools[key] + && !flags.allBools + && (aliases[key] ? !aliasIsBoolean(key) : true)) { + setArg(key, next, arg); + i++; + } + else if (/^(true|false)$/.test(next)) { + setArg(key, next === 'true', arg); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + else if (/^-[^-]+/.test(arg)) { + var letters = arg.slice(1,-1).split(''); + + var broken = false; + for (var j = 0; j < letters.length; j++) { + var next = arg.slice(j+2); + + if (next === '-') { + setArg(letters[j], next, arg) + continue; + } + + if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) { + setArg(letters[j], next.split('=')[1], arg); + broken = true; + break; + } + + if (/[A-Za-z]/.test(letters[j]) + && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { + setArg(letters[j], next, arg); + broken = true; + break; + } + + if (letters[j+1] && letters[j+1].match(/\W/)) { + setArg(letters[j], arg.slice(j+2), arg); + broken = true; + break; + } + else { + setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg); + } + } + + var key = arg.slice(-1)[0]; + if (!broken && key !== '-') { + if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1]) + && !flags.bools[key] + && (aliases[key] ? !aliasIsBoolean(key) : true)) { + setArg(key, args[i+1], arg); + i++; + } + else if (args[i+1] && /true|false/.test(args[i+1])) { + setArg(key, args[i+1] === 'true', arg); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + } + else { + if (!flags.unknownFn || flags.unknownFn(arg) !== false) { + argv._.push( + flags.strings['_'] || !isNumber(arg) ? arg : Number(arg) + ); + } + if (opts.stopEarly) { + argv._.push.apply(argv._, args.slice(i + 1)); + break; + } + } + } + + Object.keys(defaults).forEach(function (key) { + if (!hasKey(argv, key.split('.'))) { + setKey(argv, key.split('.'), defaults[key]); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), defaults[key]); + }); + } + }); + + if (opts['--']) { + argv['--'] = new Array(); + notFlags.forEach(function(key) { + argv['--'].push(key); + }); + } + else { + notFlags.forEach(function(key) { + argv._.push(key); + }); + } + + return argv; +}; + +function hasKey (obj, keys) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + o = (o[key] || {}); + }); + + var key = keys[keys.length - 1]; + return key in o; +} + +function isNumber (x) { + if (typeof x === 'number') return true; + if (/^0x[0-9a-f]+$/i.test(x)) return true; + return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x); +} +
@@ -0,0 +1,71 @@
+{ + "name": "minimist", + "version": "1.2.0", + "description": "parse argument options", + "main": "index.js", + "devDependencies": { + "covert": "^1.0.0", + "tap": "~0.4.0", + "tape": "^3.5.0" + }, + "scripts": { + "test": "tap test/*.js", + "coverage": "covert test/*.js" + }, + "testling": { + "files": "test/*.js", + "browsers": [ + "ie/6..latest", + "ff/5", + "firefox/latest", + "chrome/10", + "chrome/latest", + "safari/5.1", + "safari/latest", + "opera/12" + ] + }, + "repository": { + "type": "git", + "url": "git://github.com/substack/minimist.git" + }, + "homepage": "https://github.com/substack/minimist", + "keywords": [ + "argv", + "getopt", + "parser", + "optimist" + ], + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "license": "MIT", + "gitHead": "dc624482fcfec5bc669c68cdb861f00573ed4e64", + "bugs": { + "url": "https://github.com/substack/minimist/issues" + }, + "_id": "minimist@1.2.0", + "_shasum": "a35008b20f41383eec1fb914f4cd5df79a264284", + "_from": "minimist@>=1.1.0 <2.0.0", + "_npmVersion": "3.2.2", + "_nodeVersion": "2.4.0", + "_npmUser": { + "name": "substack", + "email": "substack@gmail.com" + }, + "dist": { + "shasum": "a35008b20f41383eec1fb914f4cd5df79a264284", + "tarball": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" + }, + "maintainers": [ + { + "name": "substack", + "email": "mail@substack.net" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,91 @@
+# minimist + +parse argument options + +This module is the guts of optimist's argument parser without all the +fanciful decoration. + +[](http://ci.testling.com/substack/minimist) + +[](http://travis-ci.org/substack/minimist) + +# example + +``` js +var argv = require('minimist')(process.argv.slice(2)); +console.dir(argv); +``` + +``` +$ node example/parse.js -a beep -b boop +{ _: [], a: 'beep', b: 'boop' } +``` + +``` +$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz +{ _: [ 'foo', 'bar', 'baz' ], + x: 3, + y: 4, + n: 5, + a: true, + b: true, + c: true, + beep: 'boop' } +``` + +# methods + +``` js +var parseArgs = require('minimist') +``` + +## var argv = parseArgs(args, opts={}) + +Return an argument object `argv` populated with the array arguments from `args`. + +`argv._` contains all the arguments that didn't have an option associated with +them. + +Numeric-looking arguments will be returned as numbers unless `opts.string` or +`opts.boolean` is set for that argument name. + +Any arguments after `'--'` will not be parsed and will end up in `argv._`. + +options can be: + +* `opts.string` - a string or array of strings argument names to always treat as +strings +* `opts.boolean` - a boolean, string or array of strings to always treat as +booleans. if `true` will treat all double hyphenated arguments without equal signs +as boolean (e.g. affects `--foo`, not `-f` or `--foo=bar`) +* `opts.alias` - an object mapping string names to strings or arrays of string +argument names to use as aliases +* `opts.default` - an object mapping string argument names to default values +* `opts.stopEarly` - when true, populate `argv._` with everything after the +first non-option +* `opts['--']` - when true, populate `argv._` with everything before the `--` +and `argv['--']` with everything after the `--`. Here's an example: +* `opts.unknown` - a function which is invoked with a command line parameter not +defined in the `opts` configuration object. If the function returns `false`, the +unknown option is not added to `argv`. + +``` +> require('./')('one two three -- four five --six'.split(' '), { '--': true }) +{ _: [ 'one', 'two', 'three' ], + '--': [ 'four', 'five', '--six' ] } +``` + +Note that with `opts['--']` set, parsing for arguments still stops after the +`--`. + +# install + +With [npm](https://npmjs.org) do: + +``` +npm install minimist +``` + +# license + +MIT
@@ -0,0 +1,32 @@
+var parse = require('../'); +var test = require('tape'); + +test('flag boolean true (default all --args to boolean)', function (t) { + var argv = parse(['moo', '--honk', 'cow'], { + boolean: true + }); + + t.deepEqual(argv, { + honk: true, + _: ['moo', 'cow'] + }); + + t.deepEqual(typeof argv.honk, 'boolean'); + t.end(); +}); + +test('flag boolean true only affects double hyphen arguments without equals signs', function (t) { + var argv = parse(['moo', '--honk', 'cow', '-p', '55', '--tacos=good'], { + boolean: true + }); + + t.deepEqual(argv, { + honk: true, + tacos: 'good', + p: 55, + _: ['moo', 'cow'] + }); + + t.deepEqual(typeof argv.honk, 'boolean'); + t.end(); +});
@@ -0,0 +1,166 @@
+var parse = require('../'); +var test = require('tape'); + +test('flag boolean default false', function (t) { + var argv = parse(['moo'], { + boolean: ['t', 'verbose'], + default: { verbose: false, t: false } + }); + + t.deepEqual(argv, { + verbose: false, + t: false, + _: ['moo'] + }); + + t.deepEqual(typeof argv.verbose, 'boolean'); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); + +}); + +test('boolean groups', function (t) { + var argv = parse([ '-x', '-z', 'one', 'two', 'three' ], { + boolean: ['x','y','z'] + }); + + t.deepEqual(argv, { + x : true, + y : false, + z : true, + _ : [ 'one', 'two', 'three' ] + }); + + t.deepEqual(typeof argv.x, 'boolean'); + t.deepEqual(typeof argv.y, 'boolean'); + t.deepEqual(typeof argv.z, 'boolean'); + t.end(); +}); +test('boolean and alias with chainable api', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = parse(aliased, { + boolean: 'herp', + alias: { h: 'herp' } + }); + var propertyArgv = parse(regular, { + boolean: 'herp', + alias: { h: 'herp' } + }); + var expected = { + herp: true, + h: true, + '_': [ 'derp' ] + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +test('boolean and alias with options hash', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var opts = { + alias: { 'h': 'herp' }, + boolean: 'herp' + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var expected = { + herp: true, + h: true, + '_': [ 'derp' ] + }; + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +test('boolean and alias array with options hash', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var alt = [ '--harp', 'derp' ]; + var opts = { + alias: { 'h': ['herp', 'harp'] }, + boolean: 'h' + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var altPropertyArgv = parse(alt, opts); + var expected = { + harp: true, + herp: true, + h: true, + '_': [ 'derp' ] + }; + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.same(altPropertyArgv, expected); + t.end(); +}); + +test('boolean and alias using explicit true', function (t) { + var aliased = [ '-h', 'true' ]; + var regular = [ '--herp', 'true' ]; + var opts = { + alias: { h: 'herp' }, + boolean: 'h' + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var expected = { + herp: true, + h: true, + '_': [ ] + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +// regression, see https://github.com/substack/node-optimist/issues/71 +test('boolean and --x=true', function(t) { + var parsed = parse(['--boool', '--other=true'], { + boolean: 'boool' + }); + + t.same(parsed.boool, true); + t.same(parsed.other, 'true'); + + parsed = parse(['--boool', '--other=false'], { + boolean: 'boool' + }); + + t.same(parsed.boool, true); + t.same(parsed.other, 'false'); + t.end(); +}); + +test('boolean --boool=true', function (t) { + var parsed = parse(['--boool=true'], { + default: { + boool: false + }, + boolean: ['boool'] + }); + + t.same(parsed.boool, true); + t.end(); +}); + +test('boolean --boool=false', function (t) { + var parsed = parse(['--boool=false'], { + default: { + boool: true + }, + boolean: ['boool'] + }); + + t.same(parsed.boool, false); + t.end(); +});
@@ -0,0 +1,31 @@
+var parse = require('../'); +var test = require('tape'); + +test('-', function (t) { + t.plan(5); + t.deepEqual(parse([ '-n', '-' ]), { n: '-', _: [] }); + t.deepEqual(parse([ '-' ]), { _: [ '-' ] }); + t.deepEqual(parse([ '-f-' ]), { f: '-', _: [] }); + t.deepEqual( + parse([ '-b', '-' ], { boolean: 'b' }), + { b: true, _: [ '-' ] } + ); + t.deepEqual( + parse([ '-s', '-' ], { string: 's' }), + { s: '-', _: [] } + ); +}); + +test('-a -- b', function (t) { + t.plan(3); + t.deepEqual(parse([ '-a', '--', 'b' ]), { a: true, _: [ 'b' ] }); + t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] }); + t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] }); +}); + +test('move arguments after the -- into their own `--` array', function(t) { + t.plan(1); + t.deepEqual( + parse([ '--name', 'John', 'before', '--', 'after' ], { '--': true }), + { name: 'John', _: [ 'before' ], '--': [ 'after' ] }); +});
@@ -0,0 +1,35 @@
+var test = require('tape'); +var parse = require('../'); + +test('boolean default true', function (t) { + var argv = parse([], { + boolean: 'sometrue', + default: { sometrue: true } + }); + t.equal(argv.sometrue, true); + t.end(); +}); + +test('boolean default false', function (t) { + var argv = parse([], { + boolean: 'somefalse', + default: { somefalse: false } + }); + t.equal(argv.somefalse, false); + t.end(); +}); + +test('boolean default to null', function (t) { + var argv = parse([], { + boolean: 'maybe', + default: { maybe: null } + }); + t.equal(argv.maybe, null); + var argv = parse(['--maybe'], { + boolean: 'maybe', + default: { maybe: null } + }); + t.equal(argv.maybe, true); + t.end(); + +})
@@ -0,0 +1,22 @@
+var parse = require('../'); +var test = require('tape'); + +test('dotted alias', function (t) { + var argv = parse(['--a.b', '22'], {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}}); + t.equal(argv.a.b, 22); + t.equal(argv.aa.bb, 22); + t.end(); +}); + +test('dotted default', function (t) { + var argv = parse('', {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}}); + t.equal(argv.a.b, 11); + t.equal(argv.aa.bb, 11); + t.end(); +}); + +test('dotted default with no alias', function (t) { + var argv = parse('', {default: {'a.b': 11}}); + t.equal(argv.a.b, 11); + t.end(); +});
@@ -0,0 +1,16 @@
+var parse = require('../'); +var test = require('tape'); + +test('short -k=v' , function (t) { + t.plan(1); + + var argv = parse([ '-b=123' ]); + t.deepEqual(argv, { b: 123, _: [] }); +}); + +test('multi short -k=v' , function (t) { + t.plan(1); + + var argv = parse([ '-a=whatever', '-b=robots' ]); + t.deepEqual(argv, { a: 'whatever', b: 'robots', _: [] }); +});
@@ -0,0 +1,31 @@
+var test = require('tape'); +var parse = require('../'); + +test('long opts', function (t) { + t.deepEqual( + parse([ '--bool' ]), + { bool : true, _ : [] }, + 'long boolean' + ); + t.deepEqual( + parse([ '--pow', 'xixxle' ]), + { pow : 'xixxle', _ : [] }, + 'long capture sp' + ); + t.deepEqual( + parse([ '--pow=xixxle' ]), + { pow : 'xixxle', _ : [] }, + 'long capture eq' + ); + t.deepEqual( + parse([ '--host', 'localhost', '--port', '555' ]), + { host : 'localhost', port : 555, _ : [] }, + 'long captures sp' + ); + t.deepEqual( + parse([ '--host=localhost', '--port=555' ]), + { host : 'localhost', port : 555, _ : [] }, + 'long captures eq' + ); + t.end(); +});
@@ -0,0 +1,36 @@
+var parse = require('../'); +var test = require('tape'); + +test('nums', function (t) { + var argv = parse([ + '-x', '1234', + '-y', '5.67', + '-z', '1e7', + '-w', '10f', + '--hex', '0xdeadbeef', + '789' + ]); + t.deepEqual(argv, { + x : 1234, + y : 5.67, + z : 1e7, + w : '10f', + hex : 0xdeadbeef, + _ : [ 789 ] + }); + t.deepEqual(typeof argv.x, 'number'); + t.deepEqual(typeof argv.y, 'number'); + t.deepEqual(typeof argv.z, 'number'); + t.deepEqual(typeof argv.w, 'string'); + t.deepEqual(typeof argv.hex, 'number'); + t.deepEqual(typeof argv._[0], 'number'); + t.end(); +}); + +test('already a number', function (t) { + var argv = parse([ '-x', 1234, 789 ]); + t.deepEqual(argv, { x : 1234, _ : [ 789 ] }); + t.deepEqual(typeof argv.x, 'number'); + t.deepEqual(typeof argv._[0], 'number'); + t.end(); +});
@@ -0,0 +1,197 @@
+var parse = require('../'); +var test = require('tape'); + +test('parse args', function (t) { + t.deepEqual( + parse([ '--no-moo' ]), + { moo : false, _ : [] }, + 'no' + ); + t.deepEqual( + parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]), + { v : ['a','b','c'], _ : [] }, + 'multi' + ); + t.end(); +}); + +test('comprehensive', function (t) { + t.deepEqual( + parse([ + '--name=meowmers', 'bare', '-cats', 'woo', + '-h', 'awesome', '--multi=quux', + '--key', 'value', + '-b', '--bool', '--no-meep', '--multi=baz', + '--', '--not-a-flag', 'eek' + ]), + { + c : true, + a : true, + t : true, + s : 'woo', + h : 'awesome', + b : true, + bool : true, + key : 'value', + multi : [ 'quux', 'baz' ], + meep : false, + name : 'meowmers', + _ : [ 'bare', '--not-a-flag', 'eek' ] + } + ); + t.end(); +}); + +test('flag boolean', function (t) { + var argv = parse([ '-t', 'moo' ], { boolean: 't' }); + t.deepEqual(argv, { t : true, _ : [ 'moo' ] }); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); +}); + +test('flag boolean value', function (t) { + var argv = parse(['--verbose', 'false', 'moo', '-t', 'true'], { + boolean: [ 't', 'verbose' ], + default: { verbose: true } + }); + + t.deepEqual(argv, { + verbose: false, + t: true, + _: ['moo'] + }); + + t.deepEqual(typeof argv.verbose, 'boolean'); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); +}); + +test('newlines in params' , function (t) { + var args = parse([ '-s', "X\nX" ]) + t.deepEqual(args, { _ : [], s : "X\nX" }); + + // reproduce in bash: + // VALUE="new + // line" + // node program.js --s="$VALUE" + args = parse([ "--s=X\nX" ]) + t.deepEqual(args, { _ : [], s : "X\nX" }); + t.end(); +}); + +test('strings' , function (t) { + var s = parse([ '-s', '0001234' ], { string: 's' }).s; + t.equal(s, '0001234'); + t.equal(typeof s, 'string'); + + var x = parse([ '-x', '56' ], { string: 'x' }).x; + t.equal(x, '56'); + t.equal(typeof x, 'string'); + t.end(); +}); + +test('stringArgs', function (t) { + var s = parse([ ' ', ' ' ], { string: '_' })._; + t.same(s.length, 2); + t.same(typeof s[0], 'string'); + t.same(s[0], ' '); + t.same(typeof s[1], 'string'); + t.same(s[1], ' '); + t.end(); +}); + +test('empty strings', function(t) { + var s = parse([ '-s' ], { string: 's' }).s; + t.equal(s, ''); + t.equal(typeof s, 'string'); + + var str = parse([ '--str' ], { string: 'str' }).str; + t.equal(str, ''); + t.equal(typeof str, 'string'); + + var letters = parse([ '-art' ], { + string: [ 'a', 't' ] + }); + + t.equal(letters.a, ''); + t.equal(letters.r, true); + t.equal(letters.t, ''); + + t.end(); +}); + + +test('string and alias', function(t) { + var x = parse([ '--str', '000123' ], { + string: 's', + alias: { s: 'str' } + }); + + t.equal(x.str, '000123'); + t.equal(typeof x.str, 'string'); + t.equal(x.s, '000123'); + t.equal(typeof x.s, 'string'); + + var y = parse([ '-s', '000123' ], { + string: 'str', + alias: { str: 's' } + }); + + t.equal(y.str, '000123'); + t.equal(typeof y.str, 'string'); + t.equal(y.s, '000123'); + t.equal(typeof y.s, 'string'); + t.end(); +}); + +test('slashBreak', function (t) { + t.same( + parse([ '-I/foo/bar/baz' ]), + { I : '/foo/bar/baz', _ : [] } + ); + t.same( + parse([ '-xyz/foo/bar/baz' ]), + { x : true, y : true, z : '/foo/bar/baz', _ : [] } + ); + t.end(); +}); + +test('alias', function (t) { + var argv = parse([ '-f', '11', '--zoom', '55' ], { + alias: { z: 'zoom' } + }); + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.f, 11); + t.end(); +}); + +test('multiAlias', function (t) { + var argv = parse([ '-f', '11', '--zoom', '55' ], { + alias: { z: [ 'zm', 'zoom' ] } + }); + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.z, argv.zm); + t.equal(argv.f, 11); + t.end(); +}); + +test('nested dotted objects', function (t) { + var argv = parse([ + '--foo.bar', '3', '--foo.baz', '4', + '--foo.quux.quibble', '5', '--foo.quux.o_O', + '--beep.boop' + ]); + + t.same(argv.foo, { + bar : 3, + baz : 4, + quux : { + quibble : 5, + o_O : true + } + }); + t.same(argv.beep, { boop : true }); + t.end(); +});
@@ -0,0 +1,9 @@
+var parse = require('../'); +var test = require('tape'); + +test('parse with modifier functions' , function (t) { + t.plan(1); + + var argv = parse([ '-b', '123' ], { boolean: 'b' }); + t.deepEqual(argv, { b: true, _: [123] }); +});
@@ -0,0 +1,67 @@
+var parse = require('../'); +var test = require('tape'); + +test('numeric short args', function (t) { + t.plan(2); + t.deepEqual(parse([ '-n123' ]), { n: 123, _: [] }); + t.deepEqual( + parse([ '-123', '456' ]), + { 1: true, 2: true, 3: 456, _: [] } + ); +}); + +test('short', function (t) { + t.deepEqual( + parse([ '-b' ]), + { b : true, _ : [] }, + 'short boolean' + ); + t.deepEqual( + parse([ 'foo', 'bar', 'baz' ]), + { _ : [ 'foo', 'bar', 'baz' ] }, + 'bare' + ); + t.deepEqual( + parse([ '-cats' ]), + { c : true, a : true, t : true, s : true, _ : [] }, + 'group' + ); + t.deepEqual( + parse([ '-cats', 'meow' ]), + { c : true, a : true, t : true, s : 'meow', _ : [] }, + 'short group next' + ); + t.deepEqual( + parse([ '-h', 'localhost' ]), + { h : 'localhost', _ : [] }, + 'short capture' + ); + t.deepEqual( + parse([ '-h', 'localhost', '-p', '555' ]), + { h : 'localhost', p : 555, _ : [] }, + 'short captures' + ); + t.end(); +}); + +test('mixed short bool and capture', function (t) { + t.same( + parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ] + } + ); + t.end(); +}); + +test('short and long', function (t) { + t.deepEqual( + parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ] + } + ); + t.end(); +});
@@ -0,0 +1,15 @@
+var parse = require('../'); +var test = require('tape'); + +test('stops parsing on the first non-option when stopEarly is set', function (t) { + var argv = parse(['--aaa', 'bbb', 'ccc', '--ddd'], { + stopEarly: true + }); + + t.deepEqual(argv, { + aaa: 'bbb', + _: ['ccc', '--ddd'] + }); + + t.end(); +});
@@ -0,0 +1,102 @@
+var parse = require('../'); +var test = require('tape'); + +test('boolean and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = [ '-h', 'true', '--derp', 'true' ]; + var regular = [ '--herp', 'true', '-d', 'true' ]; + var opts = { + alias: { h: 'herp' }, + boolean: 'h', + unknown: unknownFn + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + + t.same(unknown, ['--derp', '-d']); + t.end(); +}); + +test('flag boolean true any double hyphen argument is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var argv = parse(['--honk', '--tacos=good', 'cow', '-p', '55'], { + boolean: true, + unknown: unknownFn + }); + t.same(unknown, ['--tacos=good', 'cow', '-p']); + t.same(argv, { + honk: true, + _: [] + }); + t.end(); +}); + +test('string and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = [ '-h', 'hello', '--derp', 'goodbye' ]; + var regular = [ '--herp', 'hello', '-d', 'moon' ]; + var opts = { + alias: { h: 'herp' }, + string: 'h', + unknown: unknownFn + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + + t.same(unknown, ['--derp', '-d']); + t.end(); +}); + +test('default and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = [ '-h', 'hello' ]; + var regular = [ '--herp', 'hello' ]; + var opts = { + default: { 'h': 'bar' }, + alias: { 'h': 'herp' }, + unknown: unknownFn + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + + t.same(unknown, []); + t.end(); + unknownFn(); // exercise fn for 100% coverage +}); + +test('value following -- is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = [ '--bad', '--', 'good', 'arg' ]; + var opts = { + '--': true, + unknown: unknownFn + }; + var argv = parse(aliased, opts); + + t.same(unknown, ['--bad']); + t.same(argv, { + '--': ['good', 'arg'], + '_': [] + }) + t.end(); +});
@@ -0,0 +1,8 @@
+var parse = require('../'); +var test = require('tape'); + +test('whitespace should be whitespace' , function (t) { + t.plan(1); + var x = parse([ '-x', '\t' ]).x; + t.equal(x, '\t'); +});
@@ -0,0 +1,37 @@
+'use strict'; + +function ToObject(val) { + if (val == null) { + throw new TypeError('Object.assign cannot be called with null or undefined'); + } + + return Object(val); +} + +module.exports = Object.assign || function (target, source) { + var pendingException; + var from; + var keys; + var to = ToObject(target); + + for (var s = 1; s < arguments.length; s++) { + from = arguments[s]; + keys = Object.keys(Object(from)); + + for (var i = 0; i < keys.length; i++) { + try { + to[keys[i]] = from[keys[i]]; + } catch (err) { + if (pendingException === undefined) { + pendingException = err; + } + } + } + } + + if (pendingException) { + throw pendingException; + } + + return to; +};
@@ -0,0 +1,66 @@
+{ + "name": "object-assign", + "version": "1.0.0", + "description": "ES6 Object.assign() ponyfill", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/sindresorhus/object-assign" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "http://sindresorhus.com" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "mocha" + }, + "files": [ + "index.js" + ], + "keywords": [ + "object", + "assign", + "extend", + "properties", + "es6", + "ecmascript", + "harmony", + "ponyfill", + "prollyfill", + "polyfill", + "shim", + "browser" + ], + "devDependencies": { + "mocha": "*" + }, + "gitHead": "a17eef6882cf3ffcee46f7d9d5a5ba0abc6b029c", + "bugs": { + "url": "https://github.com/sindresorhus/object-assign/issues" + }, + "homepage": "https://github.com/sindresorhus/object-assign", + "_id": "object-assign@1.0.0", + "_shasum": "e65dc8766d3b47b4b8307465c8311da030b070a6", + "_from": "object-assign@>=1.0.0 <2.0.0", + "_npmVersion": "1.4.21", + "_npmUser": { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + } + ], + "dist": { + "shasum": "e65dc8766d3b47b4b8307465c8311da030b070a6", + "tarball": "https://registry.npmjs.org/object-assign/-/object-assign-1.0.0.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/object-assign/-/object-assign-1.0.0.tgz" +}
@@ -0,0 +1,47 @@
+# object-assign [](https://travis-ci.org/sindresorhus/object-assign) + +> ES6 [`Object.assign()`](http://www.2ality.com/2014/01/object-assign.html) ponyfill + +> Ponyfill: A polyfill that doesn't overwrite the native method + + +## Install + +```sh +$ npm install --save object-assign +``` + + +## Usage + +```js +var objectAssign = require('object-assign'); + +objectAssign({foo: 0}, {bar: 1}); +//=> {foo: 0, bar: 1} + +// multiple sources +objectAssign({foo: 0}, {bar: 1}, {baz: 3}); +//=> {foo: 0, bar: 1, baz: 2} + +// ignores null and undefined sources +objectAssign({foo: 0}, null, {bar: 1}, undefined); +//=> {foo: 0, bar: 1, baz: 2} +``` + + +## API + +### objectAssign(target, source, [source, ...]) + +Assigns enumerable own properties of `source` objects to the `target` object and returns the `target` object. Additional `source` objects will overwrite previous ones. + + +## Resources + +- [ES6 spec - Object.assign](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign) + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,67 @@
+{ + "name": "meow", + "version": "2.0.0", + "description": "CLI app helper", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/sindresorhus/meow" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "http://sindresorhus.com" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "node test.js" + }, + "files": [ + "index.js" + ], + "keywords": [ + "cli", + "bin", + "util", + "utility", + "helper", + "argv" + ], + "dependencies": { + "camelcase-keys": "^1.0.0", + "indent-string": "^1.1.0", + "minimist": "^1.1.0", + "object-assign": "^1.0.0" + }, + "devDependencies": { + "ava": "0.0.4" + }, + "gitHead": "fe0271306137c613527d38b920667d7aa4380197", + "bugs": { + "url": "https://github.com/sindresorhus/meow/issues" + }, + "homepage": "https://github.com/sindresorhus/meow", + "_id": "meow@2.0.0", + "_shasum": "8f530a8ecf5d40d3f4b4df93c3472900fba2a8f1", + "_from": "meow@>=2.0.0 <2.1.0", + "_npmVersion": "2.1.2", + "_nodeVersion": "0.10.32", + "_npmUser": { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + } + ], + "dist": { + "shasum": "8f530a8ecf5d40d3f4b4df93c3472900fba2a8f1", + "tarball": "https://registry.npmjs.org/meow/-/meow-2.0.0.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/meow/-/meow-2.0.0.tgz" +}
@@ -0,0 +1,97 @@
+# meow [](https://travis-ci.org/sindresorhus/meow) + +> CLI app helper + + + + +## Features + +- Parses arguments using [minimist](https://github.com/substack/minimist) +- Converts flags to [camelCase](https://github.com/sindresorhus/camelcase) +- Outputs version when `--version` +- Outputs description and supplied help text when `--help` + + +## Install + +```sh +$ npm install --save meow +``` + + +## Usage + +```sh +$ ./foo-app.js unicorns --rainbow-cake +``` + +```js +#!/usr/bin/env node +'use strict'; +var meow = require('meow'); +var fooApp = require('./'); + +var cli = meow({ + help: [ + 'Usage', + ' foo-app <input>' + ].join('\n') +}); +/* +{ + input: ['unicorns'], + flags: {rainbowCake: true}, + ... +} +*/ + +fooApp(cli.input[0], cli.flags); +``` + + +## API + +### meow(options, minimistOptions) + +Returns an object with: + +- `input` *(array)* - Non-flag arguments +- `flags` *(object)* - Flags converted to camelCase +- `pkg` *(object)* - The `package.json` object +- `help` *(object)* - The help text used with `--help` +- `showHelp()` *(function)* - Show the help text and exit + +#### options + +##### help + +Type: `string` + +The help text you want shown. + +##### pkg + +Type: `string` +Default: `package.json` + +Relative path to `package.json`. + +##### argv + +Type: `array` +Default: `process.argv.slice(2)` + +Custom arguments object. + +#### minimistOptions + +Type: `object` +Default: `{}` + +Minimist [options](https://github.com/substack/minimist#var-argv--parseargsargs-opts). + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com)
@@ -0,0 +1,61 @@
+{ + "name": "base64url", + "version": "1.0.6", + "description": "For encoding to/from base64urls", + "main": "index.js", + "bin": { + "base64url": "./bin/base64url" + }, + "scripts": { + "test": "tap test/*.test.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/brianloveswords/base64url.git" + }, + "keywords": [ + "base64", + "base64url" + ], + "author": { + "name": "Brian J Brennan" + }, + "license": "MIT", + "gitHead": "a219306e93712cb4380286b44360fea4406d49d3", + "devDependencies": { + "tap": "~0.3.3" + }, + "dependencies": { + "concat-stream": "~1.4.7", + "meow": "~2.0.0" + }, + "bugs": { + "url": "https://github.com/brianloveswords/base64url/issues" + }, + "homepage": "https://github.com/brianloveswords/base64url#readme", + "_id": "base64url@1.0.6", + "_shasum": "d64d375d68a7c640d912e2358d170dca5bb54681", + "_from": "base64url@>=1.0.4 <1.1.0", + "_npmVersion": "3.3.12", + "_nodeVersion": "5.2.0", + "_npmUser": { + "name": "brianloveswords", + "email": "brianloveswords@gmail.com" + }, + "maintainers": [ + { + "name": "brianloveswords", + "email": "brian@nyhacker.org" + } + ], + "dist": { + "shasum": "d64d375d68a7c640d912e2358d170dca5bb54681", + "tarball": "https://registry.npmjs.org/base64url/-/base64url-1.0.6.tgz" + }, + "_npmOperationalInternal": { + "host": "packages-9-west.internal.npmjs.com", + "tmp": "tmp/base64url-1.0.6.tgz_1455309394658_0.6706331633031368" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/base64url/-/base64url-1.0.6.tgz" +}
@@ -0,0 +1,126 @@
+# base64url [](http://travis-ci.org/brianloveswords/base64url) + +Converting to, and from, [base64url](http://en.wikipedia.org/wiki/Base64#RFC_4648) + +# Install + +```bash +$ npm install base64url +``` + +# Usage + +## CLI + +```bash +$ npm install -g base64url + +$ echo 'Here is some text to encode' | base64url +> SGVyZSBpcyBzb21lIHRleHQgdG8gZW5jb2RlCg + +$ echo SGVyZSBpcyBzb21lIHRleHQgdG8gZW5jb2RlCg | base64url -D +> Here is some text to encode + +$ base64url --help + + For encoding to/from base64urls + + Usage: base64url [-hvD] [-b num] [-i in_file] [-o out_file] + -h, --help display this message + -v, --version display version info + -D, --decode decodes input + -b, --break break encoded string into num character lines + -i, --input input file (default: stdin) + -o, --output output file (default: stdout), +``` + +## Library + +### base64url(stringOrBuffer) ### + +### base64url.encode(stringOrBuffer) ### + +base64url encode `stringOrBuffer` + + +Example + +```js +> base64url('ladies and gentlemen, we are floating in space') +'bGFkaWVzIGFuZCBnZW50bGVtYW4sIHdlIGFyZSBmbG9hdGluZyBpbiBzcGFjZQ' +``` + +--- + +### base64url.decode(b64UrlEncodedString, [encoding]) + +Convert a base64url encoded string into a raw string. Encoding defaults to `'utf8'`. + +```js +> base64url.decode('cmlkZTogZHJlYW1zIGJ1cm4gZG93bg') +'ride: dreams burn down' +``` + +--- + +### base64url.fromBase64(b64EncodedString) + +Convert a base64 encoded string to a base64url encoded string + +Example + +```js +> base64url.fromBase64('qL8R4QIcQ/ZsRqOAbeRfcZhilN/MksRtDaErMA==') +'qL8R4QIcQ_ZsRqOAbeRfcZhilN_MksRtDaErMA' +``` + +--- + + +### base64url.toBase64(b64UrlEncodedString) + +Convert a base64url encoded string to a base64 encoded string + +```js +> base64url.toBase64('qL8R4QIcQ_ZsRqOAbeRfcZhilN_MksRtDaErMA') +'qL8R4QIcQ/ZsRqOAbeRfcZhilN/MksRtDaErMA==' +``` + +--- + + +### base64url.toBuffer(b64UrlEncodedString) + +Convert a base64url encoded string to a Buffer + +```js +> base64url.toBuffer('c3Bpcml0dWFsaXplZA') +<Buffer 73 70 69 72 69 74 75 61 6c 69 7a 65 64> +``` + +# License + +MIT + +``` +Copyright (c) 2014 Brian J. Brennan + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +```
@@ -0,0 +1,56 @@
+const fs = require('fs'); +const test = require('tap').test; +const base64url = require('..'); +const testBuffer = fs.readFileSync(__dirname + '/test.jpg'); + +function base64(s) { + return Buffer(s, 'binary').toString('base64'); +} + +test('from string to base64url', function (t) { + const b64 = base64(testBuffer); + const b64url = base64url(testBuffer, 'binary'); + t.same(b64url.indexOf('+'), -1, 'should not contain plus signs'); + t.same(b64url.indexOf('/'), -1, 'should not contain slashes'); + t.same(b64url.indexOf('='), -1, 'should not contain equal signs'); + t.same(b64.indexOf('+'), b64url.indexOf('-'), 'should replace + with -'); + t.same(b64.indexOf('/'), b64url.indexOf('_'), 'should replace / with _'); + t.end(); +}); + +test('from base64url to base64', function (t) { + const b64 = base64(testBuffer); + const b64url = base64url(testBuffer, 'binary'); + const result = base64url.toBase64(b64url); + t.same(result, b64, 'should be able to convert back'); + t.end(); +}); + +test('from base64 to base64url', function (t) { + const b64 = base64(testBuffer); + const b64url = base64url(testBuffer, 'binary'); + const result = base64url.fromBase64(b64); + t.same(result, b64url, 'should be able to convert to b64url from b64'); + t.end(); +}); + +test('from base64url to string', function (t) { + const b64url = base64url(testBuffer, 'binary'); + const result = base64url.decode(b64url, 'binary'); + t.same(result, testBuffer.toString('binary'), 'should be able to decode'); + t.end(); +}); + +test('from base64url to string (buffer)', function (t) { + const b64url = base64url(testBuffer, 'binary'); + const result = base64url.decode(new Buffer(b64url), 'binary'); + t.same(result, testBuffer.toString('binary'), 'should be able to decode'); + t.end(); +}); + +test('from base64url to buffer', function (t) { + const b64url = base64url(testBuffer, 'binary'); + const result = base64url.toBuffer(b64url); + t.same(result, testBuffer, 'should be able to convert to buffer'); + t.end(); +});
@@ -0,0 +1,4 @@
+node_modules +test/*.pem +test/keys +test/*.txt
@@ -0,0 +1,11 @@
+language: node_js +node_js: + - 0.10 + - 0.11 + - 0.12 + - 4 + - 5 +notifications: + email: + recipients: + - brianloveswords@gmail.com
@@ -0,0 +1,17 @@
+Copyright (c) 2013 Brian J. Brennan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,32 @@
+verbose: test/keys + @node test/*.test.js + +test: test/keys + @./node_modules/.bin/tap test/*.test.js + +test/keys: + @openssl genrsa 2048 > test/rsa-private.pem + @openssl genrsa 2048 > test/rsa-wrong-private.pem + @openssl genrsa 2048 -passout pass:test_pass > test/rsa-passphrase-private.pem + @openssl rsa -in test/rsa-private.pem -pubout > test/rsa-public.pem + @openssl rsa -in test/rsa-wrong-private.pem -pubout > test/rsa-wrong-public.pem + @openssl rsa -in test/rsa-passphrase-private.pem -pubout -passin pass:test_pass > test/rsa-passphrase-public.pem + @openssl ecparam -out test/ec256-private.pem -name prime256v1 -genkey + @openssl ecparam -out test/ec256-wrong-private.pem -name secp256k1 -genkey + @openssl ecparam -out test/ec384-private.pem -name secp384r1 -genkey + @openssl ecparam -out test/ec384-wrong-private.pem -name secp384r1 -genkey + @openssl ecparam -out test/ec512-private.pem -name secp521r1 -genkey + @openssl ecparam -out test/ec512-wrong-private.pem -name secp521r1 -genkey + @openssl ec -in test/ec256-private.pem -pubout > test/ec256-public.pem + @openssl ec -in test/ec256-wrong-private.pem -pubout > test/ec256-wrong-public.pem + @openssl ec -in test/ec384-private.pem -pubout > test/ec384-public.pem + @openssl ec -in test/ec384-wrong-private.pem -pubout > test/ec384-wrong-public.pem + @openssl ec -in test/ec512-private.pem -pubout > test/ec512-public.pem + @openssl ec -in test/ec512-wrong-private.pem -pubout > test/ec512-wrong-public.pem + @touch test/keys + +clean: + @rm test/*.pem + @rm test/keys + +.PHONY: test
@@ -0,0 +1,145 @@
+# node-jwa [](https://travis-ci.org/brianloveswords/node-jwa) + +A +[JSON Web Algorithms](http://tools.ietf.org/id/draft-ietf-jose-json-web-algorithms-08.html) +implementation focusing (exclusively, at this point) on the algorithms necessary for +[JSON Web Signatures](http://self-issued.info/docs/draft-ietf-jose-json-web-signature.html). + +This library supports all of the required, recommended and optional cryptographic algorithms for JWS: + +alg Parameter Value | Digital Signature or MAC Algorithm +----------------|---------------------------- +HS256 | HMAC using SHA-256 hash algorithm +HS384 | HMAC using SHA-384 hash algorithm +HS512 | HMAC using SHA-512 hash algorithm +RS256 | RSASSA using SHA-256 hash algorithm +RS384 | RSASSA using SHA-384 hash algorithm +RS512 | RSASSA using SHA-512 hash algorithm +ES256 | ECDSA using P-256 curve and SHA-256 hash algorithm +ES384 | ECDSA using P-384 curve and SHA-384 hash algorithm +ES512 | ECDSA using P-521 curve and SHA-512 hash algorithm +none | No digital signature or MAC value included + +# Requirements + +In order to run the tests, a recent version of OpenSSL is +required. **The version that comes with OS X (OpenSSL 0.9.8r 8 Feb +2011) is not recent enough**, as it does not fully support ECDSA +keys. You'll need to use a version > 1.0.0; I tested with OpenSSL 1.0.1c 10 May 2012. + +# Testing + +To run the tests, do + +```bash +$ npm test +``` + +This will generate a bunch of keypairs to use in testing. If you want to +generate new keypairs, do `make clean` before running `npm test` again. + +## Methodology + +I spawn `openssl dgst -sign` to test OpenSSL sign → JS verify and +`openssl dgst -verify` to test JS sign → OpenSSL verify for each of the +RSA and ECDSA algorithms. + +# Usage + +## jwa(algorithm) + +Creates a new `jwa` object with `sign` and `verify` methods for the +algorithm. Valid values for algorithm can be found in the table above +(`'HS256'`, `'HS384'`, etc) and are case-insensitive. Passing an invalid +algorithm value will throw a `TypeError`. + + +## jwa#sign(input, secretOrPrivateKey) + +Sign some input with either a secret for HMAC algorithms, or a private +key for RSA and ECDSA algorithms. + +If input is not already a string or buffer, `JSON.stringify` will be +called on it to attempt to coerce it. + +For the HMAC algorithm, `secretOrPrivateKey` should be a string or a +buffer. For ECDSA and RSA, the value should be a string representing a +PEM encoded **private** key. + +Output [base64url](http://en.wikipedia.org/wiki/Base64#URL_applications) +formatted. This is for convenience as JWS expects the signature in this +format. If your application needs the output in a different format, +[please open an issue](https://github.com/brianloveswords/node-jwa/issues). In +the meantime, you can use +[brianloveswords/base64url](https://github.com/brianloveswords/base64url) +to decode the signature. + +As of nodejs *v0.11.8*, SPKAC support was introduce. If your nodeJs +version satisfies, then you can pass an object `{ key: '..', passphrase: '...' }` + + +## jwa#verify(input, signature, secretOrPublicKey) + +Verify a signature. Returns `true` or `false`. + +`signature` should be a base64url encoded string. + +For the HMAC algorithm, `secretOrPublicKey` should be a string or a +buffer. For ECDSA and RSA, the value should be a string represented a +PEM encoded **public** key. + + +# Example + +HMAC +```js +const jwa = require('jwa'); + +const hmac = jwa('HS256'); +const input = 'super important stuff'; +const secret = 'shhhhhh'; + +const signature = hmac.sign(input, secret); +hmac.verify(input, signature, secret) // === true +hmac.verify(input, signature, 'trickery!') // === false +``` + +With keys +```js +const fs = require('fs'); +const jwa = require('jwa'); +const privateKey = fs.readFileSync(__dirname + '/ecdsa-p521-private.pem'); +const publicKey = fs.readFileSync(__dirname + '/ecdsa-p521-public.pem'); + +const ecdsa = jwa('ES512'); +const input = 'very important stuff'; + +const signature = ecdsa.sign(input, privateKey); +ecdsa.verify(input, signature, publicKey) // === true +``` +## License + +MIT + +``` +Copyright (c) 2013 Brian J. Brennan + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +```
@@ -0,0 +1,124 @@
+var bufferEqual = require('buffer-equal-constant-time'); +var base64url = require('base64url'); +var crypto = require('crypto'); +var formatEcdsa = require('ecdsa-sig-formatter'); +var util = require('util'); + +var MSG_INVALID_ALGORITHM = '"%s" is not a valid algorithm.\n Supported algorithms are:\n "HS256", "HS384", "HS512", "RS256", "RS384", "RS512" and "none".' +var MSG_INVALID_SECRET = 'secret must be a string or buffer'; +var MSG_INVALID_VERIFIER_KEY = 'key must be a string or a buffer'; +var MSG_INVALID_SIGNER_KEY = 'key must be a string, a buffer or an object'; + +function typeError(template) { + var args = [].slice.call(arguments, 1); + var errMsg = util.format.bind(util, template).apply(null, args); + return new TypeError(errMsg); +} + +function bufferOrString(obj) { + return Buffer.isBuffer(obj) || typeof obj === 'string'; +} + +function normalizeInput(thing) { + if (!bufferOrString(thing)) + thing = JSON.stringify(thing); + return thing; +} + +function createHmacSigner(bits) { + return function sign(thing, secret) { + if (!bufferOrString(secret)) + throw typeError(MSG_INVALID_SECRET); + thing = normalizeInput(thing); + var hmac = crypto.createHmac('sha' + bits, secret); + var sig = (hmac.update(thing), hmac.digest('base64')) + return base64url.fromBase64(sig); + } +} + +function createHmacVerifier(bits) { + return function verify(thing, signature, secret) { + var computedSig = createHmacSigner(bits)(thing, secret); + return bufferEqual(Buffer(signature), Buffer(computedSig)); + } +} + +function createKeySigner(bits) { + return function sign(thing, privateKey) { + if (!bufferOrString(privateKey) && !(typeof privateKey === 'object')) + throw typeError(MSG_INVALID_SIGNER_KEY); + thing = normalizeInput(thing); + // Even though we are specifying "RSA" here, this works with ECDSA + // keys as well. + var signer = crypto.createSign('RSA-SHA' + bits); + var sig = (signer.update(thing), signer.sign(privateKey, 'base64')); + return base64url.fromBase64(sig); + } +} + +function createKeyVerifier(bits) { + return function verify(thing, signature, publicKey) { + if (!bufferOrString(publicKey)) + throw typeError(MSG_INVALID_VERIFIER_KEY); + thing = normalizeInput(thing); + signature = base64url.toBase64(signature); + var verifier = crypto.createVerify('RSA-SHA' + bits); + verifier.update(thing); + return verifier.verify(publicKey, signature, 'base64'); + } +} + +function createECDSASigner(bits) { + var inner = createKeySigner(bits); + return function sign() { + var signature = inner.apply(null, arguments); + signature = formatEcdsa.derToJose(signature, 'ES' + bits); + return signature; + }; +} + +function createECDSAVerifer(bits) { + var inner = createKeyVerifier(bits); + return function verify(thing, signature, publicKey) { + signature = formatEcdsa.joseToDer(signature, 'ES' + bits).toString('base64'); + var result = inner(thing, signature, publicKey); + return result; + }; +} + +function createNoneSigner() { + return function sign() { + return ''; + } +} + +function createNoneVerifier() { + return function verify(thing, signature) { + return signature === ''; + } +} + +module.exports = function jwa(algorithm) { + var signerFactories = { + hs: createHmacSigner, + rs: createKeySigner, + es: createECDSASigner, + none: createNoneSigner, + } + var verifierFactories = { + hs: createHmacVerifier, + rs: createKeyVerifier, + es: createECDSAVerifer, + none: createNoneVerifier, + } + var match = algorithm.match(/^(RS|ES|HS)(256|384|512)$|^(none)$/i); + if (!match) + throw typeError(MSG_INVALID_ALGORITHM, algorithm); + var algo = (match[1] || match[3]).toLowerCase(); + var bits = match[2]; + + return { + sign: signerFactories[algo](bits), + verify: verifierFactories[algo](bits), + } +};
@@ -0,0 +1,2 @@
+.*.sw[mnop] +node_modules/
@@ -0,0 +1,4 @@
+language: node_js +node_js: +- "0.11" +- "0.10"
@@ -0,0 +1,12 @@
+Copyright (c) 2013, GoInstant Inc., a salesforce.com company +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +* Neither the name of salesforce.com, nor GoInstant, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,50 @@
+# buffer-equal-constant-time + +Constant-time `Buffer` comparison for node.js. Should work with browserify too. + +[](https://travis-ci.org/goinstant/buffer-equal-constant-time) + +```sh + npm install buffer-equal-constant-time +``` + +# Usage + +```js + var bufferEq = require('buffer-equal-constant-time'); + + var a = new Buffer('asdf'); + var b = new Buffer('asdf'); + if (bufferEq(a,b)) { + // the same! + } else { + // different in at least one byte! + } +``` + +If you'd like to install an `.equal()` method onto the node.js `Buffer` and +`SlowBuffer` prototypes: + +```js + require('buffer-equal-constant-time').install(); + + var a = new Buffer('asdf'); + var b = new Buffer('asdf'); + if (a.equal(b)) { + // the same! + } else { + // different in at least one byte! + } +``` + +To get rid of the installed `.equal()` method, call `.restore()`: + +```js + require('buffer-equal-constant-time').restore(); +``` + +# Legal + +© 2013 GoInstant Inc., a salesforce.com company + +Licensed under the BSD 3-clause license.
@@ -0,0 +1,41 @@
+/*jshint node:true */ +'use strict'; +var Buffer = require('buffer').Buffer; // browserify +var SlowBuffer = require('buffer').SlowBuffer; + +module.exports = bufferEq; + +function bufferEq(a, b) { + + // shortcutting on type is necessary for correctness + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + return false; + } + + // buffer sizes should be well-known information, so despite this + // shortcutting, it doesn't leak any information about the *contents* of the + // buffers. + if (a.length !== b.length) { + return false; + } + + var c = 0; + for (var i = 0; i < a.length; i++) { + /*jshint bitwise:false */ + c |= a[i] ^ b[i]; // XOR + } + return c === 0; +} + +bufferEq.install = function() { + Buffer.prototype.equal = SlowBuffer.prototype.equal = function equal(that) { + return bufferEq(this, that); + }; +}; + +var origBufEqual = Buffer.prototype.equal; +var origSlowBufEqual = SlowBuffer.prototype.equal; +bufferEq.restore = function() { + Buffer.prototype.equal = origBufEqual; + SlowBuffer.prototype.equal = origSlowBufEqual; +};
@@ -0,0 +1,51 @@
+{ + "name": "buffer-equal-constant-time", + "version": "1.0.1", + "description": "Constant-time comparison of Buffers", + "main": "index.js", + "scripts": { + "test": "mocha test.js" + }, + "repository": { + "type": "git", + "url": "git@github.com:goinstant/buffer-equal-constant-time.git" + }, + "keywords": [ + "buffer", + "equal", + "constant-time", + "crypto" + ], + "author": { + "name": "GoInstant Inc., a salesforce.com company" + }, + "license": "BSD-3-Clause", + "devDependencies": { + "mocha": "~1.15.1" + }, + "readme": "# buffer-equal-constant-time\n\nConstant-time `Buffer` comparison for node.js. Should work with browserify too.\n\n[](https://travis-ci.org/goinstant/buffer-equal-constant-time)\n\n```sh\n npm install buffer-equal-constant-time\n```\n\n# Usage\n\n```js\n var bufferEq = require('buffer-equal-constant-time');\n\n var a = new Buffer('asdf');\n var b = new Buffer('asdf');\n if (bufferEq(a,b)) {\n // the same!\n } else {\n // different in at least one byte!\n }\n```\n\nIf you'd like to install an `.equal()` method onto the node.js `Buffer` and\n`SlowBuffer` prototypes:\n\n```js\n require('buffer-equal-constant-time').install();\n\n var a = new Buffer('asdf');\n var b = new Buffer('asdf');\n if (a.equal(b)) {\n // the same!\n } else {\n // different in at least one byte!\n }\n```\n\nTo get rid of the installed `.equal()` method, call `.restore()`:\n\n```js\n require('buffer-equal-constant-time').restore();\n```\n\n# Legal\n\n© 2013 GoInstant Inc., a salesforce.com company\n\nLicensed under the BSD 3-clause license.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/goinstant/buffer-equal-constant-time/issues" + }, + "_id": "buffer-equal-constant-time@1.0.1", + "dist": { + "shasum": "f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819", + "tarball": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz" + }, + "_from": "buffer-equal-constant-time@>=1.0.1 <2.0.0", + "_npmVersion": "1.3.11", + "_npmUser": { + "name": "goinstant", + "email": "support@goinstant.com" + }, + "maintainers": [ + { + "name": "goinstant", + "email": "support@goinstant.com" + } + ], + "directories": {}, + "_shasum": "f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819", + "_resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz" +}
@@ -0,0 +1,42 @@
+/*jshint node:true */ +'use strict'; + +var bufferEq = require('./index'); +var assert = require('assert'); + +describe('buffer-equal-constant-time', function() { + var a = new Buffer('asdfasdf123456'); + var b = new Buffer('asdfasdf123456'); + var c = new Buffer('asdfasdf'); + + describe('bufferEq', function() { + it('says a == b', function() { + assert.strictEqual(bufferEq(a, b), true); + }); + + it('says a != c', function() { + assert.strictEqual(bufferEq(a, c), false); + }); + }); + + describe('install/restore', function() { + before(function() { + bufferEq.install(); + }); + after(function() { + bufferEq.restore(); + }); + + it('installed an .equal method', function() { + var SlowBuffer = require('buffer').SlowBuffer; + assert.ok(Buffer.prototype.equal); + assert.ok(SlowBuffer.prototype.equal); + }); + + it('infected existing Buffers', function() { + assert.strictEqual(a.equal(b), true); + assert.strictEqual(a.equal(c), false); + }); + }); + +});
@@ -0,0 +1,201 @@
+Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2015 D2L Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
@@ -0,0 +1,65 @@
+# ecdsa-sig-formatter + +[](https://travis-ci.org/Brightspace/node-ecdsa-sig-formatter) [](https://coveralls.io/r/Brightspace/node-ecdsa-sig-formatter) + +Translate between JOSE and ASN.1/DER encodings for ECDSA signatures + +## Install +```sh +npm install ecdsa-sig-formatter --save +``` + +## Usage +```js +var format = require('ecdsa-sig-formatter'); + +var derSignature = '..'; // asn.1/DER encoded ecdsa signature + +var joseSignature = format.derToJose(derSignature); + +``` + +### API + +--- + +#### `.derToJose(Buffer|String signature, String alg)` -> `String` + +Convert the ASN.1/DER encoded signature to a JOSE-style concatenated signature. +Returns a _base64 url_ encoded `String`. + +* If _signature_ is a `String`, it should be _base64_ encoded +* _alg_ must be one of _ES256_, _ES384_ or _ES512_ + +--- + +#### `.joseToDer(Buffer|String signature, String alg)` -> `Buffer` + +Convert the JOSE-style concatenated signature to an ASN.1/DER encoded +signature. Returns a `Buffer` + +* If _signature_ is a `String`, it should be _base64 url_ encoded +* _alg_ must be one of _ES256_, _ES384_ or _ES512_ + +## Contributing + +1. **Fork** the repository. Committing directly against this repository is + highly discouraged. + +2. Make your modifications in a branch, updating and writing new unit tests + as necessary in the `spec` directory. + +3. Ensure that all tests pass with `npm test` + +4. `rebase` your changes against master. *Do not merge*. + +5. Submit a pull request to this repository. Wait for tests to run and someone + to chime in. + +### Code Style + +This repository is configured with [EditorConfig][EditorConfig] and +[ESLint][ESLint] rules. + +[EditorConfig]: http://editorconfig.org/ +[ESLint]: http://eslint.org
@@ -0,0 +1,15 @@
+The ISC License + +Copyright (c) 2014, Joaquim José F. Serafim + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -0,0 +1,50 @@
+# base64-url + +Base64 encode, decode, escape and unescape for URL applications. + +<a href="https://nodei.co/npm/base64-url/"><img src="https://nodei.co/npm/base64-url.png?downloads=true"></a> + +[](https://travis-ci.org/joaquimserafim/base64-url) + + +## API + +```js +base64url.encode('Node.js is awesome.'); +// returns Tm9kZS5qcyBpcyBhd2Vzb21lLg + +base64url.decode('Tm9kZS5qcyBpcyBhd2Vzb21lLg'); +// returns Node.js is awesome. + +base64url.escape('This+is/goingto+escape=='); +// returns This-is_goingto-escape + +base64url.unescape('This-is_goingto-escape'); +// returns This+is/goingto+escape== +``` + + +## Development + +**this projet has been set up with a precommit that forces you to follow a code style, no jshint issues and 100% of code coverage before commit** + + +to run test +``` js +npm test +``` + +to run lint +``` js +npm run lint +``` + +to run code style +``` js +npm run style +``` + +to check code coverage +``` js +npm run coverage:check +```
@@ -0,0 +1,23 @@
+'use strict'; + +var base64url = module.exports; + +base64url.unescape = function unescape (str) { + return (str + '==='.slice((str.length + 3) % 4)) + .replace(/\-/g, '+') + .replace(/_/g, '/'); +}; + +base64url.escape = function escape (str) { + return str.replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=/g, ''); +}; + +base64url.encode = function encode (str) { + return this.escape(new Buffer(str).toString('base64')); +}; + +base64url.decode = function decode (str) { + return new Buffer(this.unescape(str), 'base64').toString(); +};
@@ -0,0 +1,73 @@
+{ + "name": "base64-url", + "version": "1.3.2", + "description": "Base64 encode, decode, escape and unescape for URL applications", + "main": "index.js", + "files": [ + "LICENSE", + "README.md", + "index.js" + ], + "scripts": { + "test": "istanbul cover tape test.js", + "lint": "jshint -c .jshintrc *.js", + "style": "jscs -p google *.js", + "coverage:check": "istanbul check-coverage --statements 100 --functions 100 --lines 100 --branches 100", + "coverage": "open coverage/lcov-report/index.html" + }, + "repository": { + "type": "git", + "url": "git://github.com/joaquimserafim/base64-url.git" + }, + "keywords": [ + "base64", + "base64url" + ], + "author": { + "name": "@joaquimserafim" + }, + "license": "ISC", + "bugs": { + "url": "https://github.com/joaquimserafim/base64-url/issues" + }, + "homepage": "https://github.com/joaquimserafim/base64-url", + "devDependencies": { + "istanbul": "^0.3.5", + "jscs": "^1.9.0", + "jshint": "^2.5.11", + "pre-commit": "^1.1.3", + "tape": "^4.6.0" + }, + "pre-commit": [ + "lint", + "style", + "test", + "coverage:check" + ], + "gitHead": "356442c220fe38d00fa34078519c9b3ac31b1312", + "_id": "base64-url@1.3.2", + "_shasum": "4b08113b49d23889f306be64372762d31412f7a8", + "_from": "base64-url@>=1.2.1 <2.0.0", + "_npmVersion": "2.15.0", + "_nodeVersion": "4.4.2", + "_npmUser": { + "name": "quim", + "email": "joaquim.serafim@gmail.com" + }, + "dist": { + "shasum": "4b08113b49d23889f306be64372762d31412f7a8", + "tarball": "https://registry.npmjs.org/base64-url/-/base64-url-1.3.2.tgz" + }, + "maintainers": [ + { + "name": "quim", + "email": "joaquim.serafim@gmail.com" + } + ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/base64-url-1.3.2.tgz_1468593630635_0.8208693880587816" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/base64-url/-/base64-url-1.3.2.tgz" +}
@@ -0,0 +1,73 @@
+{ + "name": "ecdsa-sig-formatter", + "version": "1.0.7", + "description": "Translate ECDSA signatures between ASN.1/DER and JOSE-style concatenation", + "main": "src/ecdsa-sig-formatter.js", + "scripts": { + "check-style": "eslint .", + "pretest": "npm run check-style", + "test": "istanbul cover --root src _mocha -- spec", + "report-cov": "cat ./coverage/lcov.info | coveralls" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/Brightspace/node-ecdsa-sig-formatter.git" + }, + "keywords": [ + "ecdsa", + "der", + "asn.1", + "jwt", + "jwa", + "jsonwebtoken", + "jose" + ], + "author": { + "name": "D2L Corporation" + }, + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/Brightspace/node-ecdsa-sig-formatter/issues" + }, + "homepage": "https://github.com/Brightspace/node-ecdsa-sig-formatter#readme", + "dependencies": { + "base64-url": "^1.2.1" + }, + "devDependencies": { + "bench": "^0.3.6", + "chai": "^3.5.0", + "coveralls": "^2.11.9", + "elliptic": "^6.3.1", + "eslint": "^2.12.0", + "eslint-config-brightspace": "^0.2.1", + "istanbul": "^0.4.3", + "jwk-to-pem": "^1.2.5", + "mocha": "^2.5.3" + }, + "gitHead": "eed19df2c57d8ab04dee02f151ae7ed7bbdbba8f", + "_id": "ecdsa-sig-formatter@1.0.7", + "_shasum": "3137e976a1d6232517e2513e04e32f79bcbdf126", + "_from": "ecdsa-sig-formatter@>=1.0.0 <2.0.0", + "_npmVersion": "3.8.6", + "_nodeVersion": "5.11.1", + "_npmUser": { + "name": "d2l-travis-deploy", + "email": "d2ltravisdeploy@d2l.com" + }, + "dist": { + "shasum": "3137e976a1d6232517e2513e04e32f79bcbdf126", + "tarball": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.7.tgz" + }, + "maintainers": [ + { + "name": "d2l-travis-deploy", + "email": "d2ltravisdeploy@d2l.com" + } + ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/ecdsa-sig-formatter-1.0.7.tgz_1466263566774_0.3799667169805616" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.7.tgz" +}
@@ -0,0 +1,180 @@
+'use strict'; + +var base64Url = require('base64-url').escape; + +var getParamBytesForAlg = require('./param-bytes-for-alg'); + +var MAX_OCTET = 0x80, + CLASS_UNIVERSAL = 0, + PRIMITIVE_BIT = 0x20, + TAG_SEQ = 0x10, + TAG_INT = 0x02, + ENCODED_TAG_SEQ = (TAG_SEQ | PRIMITIVE_BIT) | (CLASS_UNIVERSAL << 6), + ENCODED_TAG_INT = TAG_INT | (CLASS_UNIVERSAL << 6); + +function signatureAsBuffer(signature) { + if (Buffer.isBuffer(signature)) { + return signature; + } else if ('string' === typeof signature) { + return new Buffer(signature, 'base64'); + } + + throw new TypeError('ECDSA signature must be a Base64 string or a Buffer'); +} + +function derToJose(signature, alg) { + signature = signatureAsBuffer(signature); + var paramBytes = getParamBytesForAlg(alg); + + // the DER encoded param should at most be the param size, plus a padding + // zero, since due to being a signed integer + var maxEncodedParamLength = paramBytes + 1; + + var inputLength = signature.length; + + var offset = 0; + if (signature[offset++] !== ENCODED_TAG_SEQ) { + throw new Error('Could not find expected "seq"'); + } + + var seqLength = signature[offset++]; + if (seqLength === (MAX_OCTET | 1)) { + seqLength = signature[offset++]; + } + + if (inputLength - offset < seqLength) { + throw new Error('"seq" specified length of "' + seqLength + '", only "' + (inputLength - offset) + '" remaining'); + } + + if (signature[offset++] !== ENCODED_TAG_INT) { + throw new Error('Could not find expected "int" for "r"'); + } + + var rLength = signature[offset++]; + + if (inputLength - offset - 2 < rLength) { + throw new Error('"r" specified length of "' + rLength + '", only "' + (inputLength - offset - 2) + '" available'); + } + + if (maxEncodedParamLength < rLength) { + throw new Error('"r" specified length of "' + rLength + '", max of "' + maxEncodedParamLength + '" is acceptable'); + } + + var rOffset = offset; + offset += rLength; + + if (signature[offset++] !== ENCODED_TAG_INT) { + throw new Error('Could not find expected "int" for "s"'); + } + + var sLength = signature[offset++]; + + if (inputLength - offset !== sLength) { + throw new Error('"s" specified length of "' + sLength + '", expected "' + (inputLength - offset) + '"'); + } + + if (maxEncodedParamLength < sLength) { + throw new Error('"s" specified length of "' + sLength + '", max of "' + maxEncodedParamLength + '" is acceptable'); + } + + var sOffset = offset; + offset += sLength; + + if (offset !== inputLength) { + throw new Error('Expected to consume entire buffer, but "' + (inputLength - offset) + '" bytes remain'); + } + + var rPadding = paramBytes - rLength, + sPadding = paramBytes - sLength; + + var dst = new Buffer(rPadding + rLength + sPadding + sLength); + + for (offset = 0; offset < rPadding; ++offset) { + dst[offset] = 0; + } + signature.copy(dst, offset, rOffset + Math.max(-rPadding, 0), rOffset + rLength); + + offset = paramBytes; + + for (var o = offset; offset < o + sPadding; ++offset) { + dst[offset] = 0; + } + signature.copy(dst, offset, sOffset + Math.max(-sPadding, 0), sOffset + sLength); + + dst = dst.toString('base64'); + dst = base64Url(dst); + + return dst; +} + +function countPadding(buf, start, stop) { + var padding = 0; + for (var n = stop; start + padding < n && buf[start + padding] === 0;) { + ++padding; + } + + var needsSign = buf[start + padding] >= MAX_OCTET; + if (needsSign) { + --padding; + } + + return padding; +} + +function joseToDer(signature, alg) { + signature = signatureAsBuffer(signature); + var paramBytes = getParamBytesForAlg(alg); + + var signatureBytes = signature.length; + if (signatureBytes !== paramBytes * 2) { + throw new TypeError('"' + alg + '" signatures must be "' + paramBytes * 2 + '" bytes, saw "' + signatureBytes + '"'); + } + + var rPadding = countPadding(signature, 0, paramBytes); + var sPadding = countPadding(signature, paramBytes, signature.length); + var rLength = paramBytes - rPadding; + var sLength = paramBytes - sPadding; + + var rsBytes = 1 + 1 + rLength + 1 + 1 + sLength; + + var shortLength = rsBytes < MAX_OCTET; + + var dst = new Buffer((shortLength ? 2 : 3) + rsBytes); + + var offset = 0; + dst[offset++] = ENCODED_TAG_SEQ; + if (shortLength) { + // Bit 8 has value "0" + // bits 7-1 give the length. + dst[offset++] = rsBytes; + } else { + // Bit 8 of first octet has value "1" + // bits 7-1 give the number of additional length octets. + dst[offset++] = MAX_OCTET | 1; + // length, base 256 + dst[offset++] = rsBytes & 0xff; + } + dst[offset++] = ENCODED_TAG_INT; + dst[offset++] = rLength; + if (rPadding < 0) { + dst[offset++] = 0; + offset += signature.copy(dst, offset, 0, paramBytes); + } else { + offset += signature.copy(dst, offset, rPadding, paramBytes); + } + dst[offset++] = ENCODED_TAG_INT; + dst[offset++] = sLength; + if (sPadding < 0) { + dst[offset++] = 0; + signature.copy(dst, offset, paramBytes); + } else { + signature.copy(dst, offset, paramBytes + sPadding); + } + + return dst; +} + +module.exports = { + derToJose: derToJose, + joseToDer: joseToDer +};
@@ -0,0 +1,23 @@
+'use strict'; + +function getParamSize(keySize) { + var result = ((keySize / 8) | 0) + (keySize % 8 === 0 ? 0 : 1); + return result; +} + +var paramBytesForAlg = { + ES256: getParamSize(256), + ES384: getParamSize(384), + ES512: getParamSize(521) +}; + +function getParamBytesForAlg(alg) { + var paramBytes = paramBytesForAlg[alg]; + if (paramBytes) { + return paramBytes; + } + + throw new Error('Unknown algorithm "' + alg + '"'); +} + +module.exports = getParamBytesForAlg;
@@ -0,0 +1,74 @@
+{ + "name": "jwa", + "version": "1.1.3", + "description": "JWA implementation (supports all JWS algorithms)", + "main": "index.js", + "directories": { + "test": "test" + }, + "dependencies": { + "base64url": "~1.0.4", + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "^1.0.0" + }, + "devDependencies": { + "semver": "^4.3.6", + "tap": "~0.3.3" + }, + "scripts": { + "test": "make test" + }, + "repository": { + "type": "git", + "url": "git://github.com/brianloveswords/node-jwa.git" + }, + "keywords": [ + "jwa", + "jws", + "jwt", + "rsa", + "ecdsa", + "hmac" + ], + "author": { + "name": "Brian J. Brennan" + }, + "license": "MIT", + "gitHead": "5ca1d5182bb64ff15f6f52000fb30a6582a4c8b0", + "bugs": { + "url": "https://github.com/brianloveswords/node-jwa/issues" + }, + "homepage": "https://github.com/brianloveswords/node-jwa#readme", + "_id": "jwa@1.1.3", + "_shasum": "fa9f2f005ff0c630e7c41526a31f37f79733cd6d", + "_from": "jwa@>=1.1.2 <2.0.0", + "_npmVersion": "3.3.12", + "_nodeVersion": "5.2.0", + "_npmUser": { + "name": "brianloveswords", + "email": "brianloveswords@gmail.com" + }, + "maintainers": [ + { + "name": "brianloveswords", + "email": "brianloveswords@gmail.com" + }, + { + "name": "stenington", + "email": "mikelarssonftw@gmail.com" + }, + { + "name": "omsmith", + "email": "owen@omsmith.ca" + } + ], + "dist": { + "shasum": "fa9f2f005ff0c630e7c41526a31f37f79733cd6d", + "tarball": "https://registry.npmjs.org/jwa/-/jwa-1.1.3.tgz" + }, + "_npmOperationalInternal": { + "host": "packages-5-east.internal.npmjs.com", + "tmp": "tmp/jwa-1.1.3.tgz_1455809964709_0.6556255409959704" + }, + "_resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.3.tgz" +}
@@ -0,0 +1,305 @@
+const path = require('path'); +const base64url = require('base64url'); +const formatEcdsa = require('ecdsa-sig-formatter'); +const spawn = require('child_process').spawn; +const semver = require('semver'); +const fs = require('fs'); +const test = require('tap').test; +const jwa = require('..'); + +const nodeVersion = semver.clean(process.version); + +// these key files will be generated as part of `make test` +const rsaPrivateKey = fs.readFileSync(__dirname + '/rsa-private.pem').toString(); +const rsaPublicKey = fs.readFileSync(__dirname + '/rsa-public.pem').toString(); +const rsaPrivateKeyWithPassphrase = fs.readFileSync(__dirname + '/rsa-passphrase-private.pem').toString(); +const rsaPublicKeyWithPassphrase = fs.readFileSync(__dirname + '/rsa-passphrase-public.pem').toString(); +const rsaWrongPublicKey = fs.readFileSync(__dirname + '/rsa-wrong-public.pem').toString(); +const ecdsaPrivateKey = { + '256': fs.readFileSync(__dirname + '/ec256-private.pem').toString(), + '384': fs.readFileSync(__dirname + '/ec384-private.pem').toString(), + '512': fs.readFileSync(__dirname + '/ec512-private.pem').toString(), +}; +const ecdsaPublicKey = { + '256': fs.readFileSync(__dirname + '/ec256-public.pem').toString(), + '384': fs.readFileSync(__dirname + '/ec384-public.pem').toString(), + '512': fs.readFileSync(__dirname + '/ec512-public.pem').toString(), +}; +const ecdsaWrongPublicKey = { + '256': fs.readFileSync(__dirname + '/ec256-wrong-public.pem').toString(), + '384': fs.readFileSync(__dirname + '/ec384-wrong-public.pem').toString(), + '512': fs.readFileSync(__dirname + '/ec512-wrong-public.pem').toString(), +}; + +const BIT_DEPTHS = ['256', '384', '512']; + +test('HMAC signing, verifying', function (t) { + const input = 'eugene mirman'; + const secret = 'shhhhhhhhhh'; + BIT_DEPTHS.forEach(function (bits) { + const algo = jwa('hs'+bits); + const sig = algo.sign(input, secret); + t.ok(algo.verify(input, sig, secret), 'should verify'); + t.notOk(algo.verify(input, 'other sig', secret), 'should verify'); + t.notOk(algo.verify(input, sig, 'incrorect'), 'shoud not verify'); + }); + t.end(); +}); + +test('RSA signing, verifying', function (t) { + const input = 'h. jon benjamin'; + BIT_DEPTHS.forEach(function (bits) { + const algo = jwa('rs'+bits); + const sig = algo.sign(input, rsaPrivateKey); + t.ok(algo.verify(input, sig, rsaPublicKey), 'should verify'); + t.notOk(algo.verify(input, sig, rsaWrongPublicKey), 'shoud not verify'); + }); + t.end(); +}); + +// run only on nodejs version >= 0.11.8 +if (semver.gte(nodeVersion, '0.11.8')) { + test('RSA with passphrase signing, verifying', function (t) { + const input = 'test input'; + BIT_DEPTHS.forEach(function (bits) { + const algo = jwa('rs'+bits); + const secret = 'test_pass'; + const sig = algo.sign(input, {key: rsaPrivateKeyWithPassphrase, passphrase: secret}); + t.ok(algo.verify(input, sig, rsaPublicKeyWithPassphrase), 'should verify'); + }); + t.end(); + }); +} + + +BIT_DEPTHS.forEach(function (bits) { + test('RS'+bits+': openssl sign -> js verify', function (t) { + const input = 'iodine'; + const algo = jwa('rs'+bits); + const dgst = spawn('openssl', ['dgst', '-sha'+bits, '-sign', __dirname + '/rsa-private.pem']); + var buffer = Buffer(0); + dgst.stdin.end(input); + dgst.stdout.on('data', function (buf) { + buffer = Buffer.concat([buffer, buf]); + }); + dgst.on('exit', function (code) { + if (code !== 0) + return t.fail('could not test interop: openssl failure'); + const base64sig = buffer.toString('base64'); + const sig = base64url.fromBase64(base64sig); + t.ok(algo.verify(input, sig, rsaPublicKey), 'should verify'); + t.notOk(algo.verify(input, sig, rsaWrongPublicKey), 'should not verify'); + t.end(); + }); + }); +}); + +BIT_DEPTHS.forEach(function (bits) { + test('ES'+bits+': signing, verifying', function (t) { + const input = 'kristen schaal'; + const algo = jwa('es'+bits); + const sig = algo.sign(input, ecdsaPrivateKey[bits]); + t.ok(algo.verify(input, sig, ecdsaPublicKey[bits]), 'should verify'); + t.notOk(algo.verify(input, sig, ecdsaWrongPublicKey[bits]), 'should not verify'); + t.end(); + }); +}); + +BIT_DEPTHS.forEach(function (bits) { + test('ES'+bits+': openssl sign -> js verify', function (t) { + const input = 'strawberry'; + const algo = jwa('es'+bits); + const dgst = spawn('openssl', ['dgst', '-sha'+bits, '-sign', __dirname + '/ec'+bits+'-private.pem']); + var buffer = Buffer(0); + dgst.stdin.end(input); + dgst.stdout.on('data', function (buf) { + buffer = Buffer.concat([buffer, buf]); + }); + dgst.on('exit', function (code) { + if (code !== 0) + return t.fail('could not test interop: openssl failure'); + const sig = formatEcdsa.derToJose(buffer, 'ES' + bits); + t.ok(algo.verify(input, sig, ecdsaPublicKey[bits]), 'should verify'); + t.notOk(algo.verify(input, sig, ecdsaWrongPublicKey[bits]), 'should not verify'); + t.end(); + }); + }); +}); + +BIT_DEPTHS.forEach(function (bits) { + const input = 'bob\'s'; + const inputFile = path.join(__dirname, 'interop.input.txt'); + const signatureFile = path.join(__dirname, 'interop.sig.txt'); + + function opensslVerify(keyfile) { + return spawn('openssl', [ + 'dgst', + '-sha'+bits, + '-verify', keyfile, + '-signature', signatureFile, + inputFile + ]); + } + + test('ES'+bits+': js sign -> openssl verify', function (t) { + const publicKeyFile = path.join(__dirname, 'ec'+bits+'-public.pem'); + const wrongPublicKeyFile = path.join(__dirname, 'ec'+bits+'-wrong-public.pem'); + const privateKey = ecdsaPrivateKey[bits]; + const signature = + formatEcdsa.joseToDer( + jwa('es'+bits).sign(input, privateKey), + 'ES' + bits + ); + fs.writeFileSync(inputFile, input); + fs.writeFileSync(signatureFile, signature); + + t.plan(2); + opensslVerify(publicKeyFile).on('exit', function (code) { + t.same(code, 0, 'should be a successful exit'); + }); + opensslVerify(wrongPublicKeyFile).on('exit', function (code) { + t.same(code, 1, 'should be invalid'); + }); + }); +}); + +BIT_DEPTHS.forEach(function (bits) { + const input = 'burgers'; + const inputFile = path.join(__dirname, 'interop.input.txt'); + const signatureFile = path.join(__dirname, 'interop.sig.txt'); + + function opensslVerify(keyfile) { + return spawn('openssl', [ + 'dgst', + '-sha'+bits, + '-verify', keyfile, + '-signature', signatureFile, + inputFile + ]); + } + + test('RS'+bits+': js sign -> openssl verify', function (t) { + const publicKeyFile = path.join(__dirname, 'rsa-public.pem'); + const wrongPublicKeyFile = path.join(__dirname, 'rsa-wrong-public.pem'); + const privateKey = rsaPrivateKey; + const signature = + base64url.toBuffer( + jwa('rs'+bits).sign(input, privateKey) + ); + fs.writeFileSync(signatureFile, signature); + fs.writeFileSync(inputFile, input); + + t.plan(2); + opensslVerify(publicKeyFile).on('exit', function (code) { + t.same(code, 0, 'should be a successful exit'); + }); + opensslVerify(wrongPublicKeyFile).on('exit', function (code) { + t.same(code, 1, 'should be invalid'); + }); + }); +}); + + +test('jwa: none', function (t) { + const input = 'whatever'; + const algo = jwa('none'); + const sig = algo.sign(input); + t.ok(algo.verify(input, sig), 'should verify'); + t.notOk(algo.verify(input, 'something'), 'shoud not verify'); + t.end(); +}); + +test('jwa: some garbage algorithm', function (t) { + try { + jwa('something bogus'); + t.fail('should throw'); + } catch(ex) { + t.same(ex.name, 'TypeError'); + t.ok(ex.message.match(/valid algorithm/), 'should say something about algorithms'); + } + t.end(); +}); + +['ahs256b', 'anoneb', 'none256', 'rsnone'].forEach(function (superstringAlg) { + test('jwa: superstrings of other algorithms', function (t) { + try { + jwa(superstringAlg); + t.fail('should throw'); + } catch(ex) { + t.same(ex.name, 'TypeError'); + t.ok(ex.message.match(/valid algorithm/), 'should say something about algorithms'); + } + t.end(); + }); +}); + +['rs', 'es', 'hs'].forEach(function (partialAlg) { + test('jwa: partial strings of other algorithms', function (t) { + try { + jwa(partialAlg); + t.fail('should throw'); + } catch(ex) { + t.same(ex.name, 'TypeError'); + t.ok(ex.message.match(/valid algorithm/), 'should say something about algorithms'); + } + t.end(); + }); +}); + +test('jwa: hs512, missing secret', function (t) { + const algo = jwa('hs512'); + try { + algo.sign('some stuff'); + t.fail('should throw'); + } catch(ex) { + t.same(ex.name, 'TypeError'); + t.ok(ex.message.match(/secret/), 'should say something about secrets'); + } + t.end(); +}); + +test('jwa: hs512, weird input type', function (t) { + const algo = jwa('hs512'); + const input = {a: ['whatever', 'this', 'is']}; + const secret = 'bones'; + const sig = algo.sign(input, secret); + t.ok(algo.verify(input, sig, secret), 'should verify'); + t.notOk(algo.verify(input, sig, 'other thing'), 'should not verify'); + t.end(); +}); + +test('jwa: rs512, weird input type', function (t) { + const algo = jwa('rs512'); + const input = {a: ['whatever', 'this', 'is']}; + const sig = algo.sign(input, rsaPrivateKey); + t.ok(algo.verify(input, sig, rsaPublicKey), 'should verify'); + t.notOk(algo.verify(input, sig, rsaWrongPublicKey), 'should not verify'); + t.end(); +}); + +test('jwa: rs512, missing signing key', function (t) { + const algo = jwa('rs512'); + try { + algo.sign('some stuff'); + t.fail('should throw'); + } catch(ex) { + t.same(ex.name, 'TypeError'); + t.ok(ex.message.match(/key/), 'should say something about keys'); + } + t.end(); +}); + +test('jwa: rs512, missing verifying key', function (t) { + const algo = jwa('rs512'); + const input = {a: ['whatever', 'this', 'is']}; + const sig = algo.sign(input, rsaPrivateKey); + try { + algo.verify(input, sig); + t.fail('should throw'); + } catch(ex) { + t.same(ex.name, 'TypeError'); + t.ok(ex.message.match(/key/), 'should say something about keys'); + } + t.end(); +}); +
@@ -0,0 +1,71 @@
+{ + "name": "jws", + "version": "3.1.3", + "description": "Implementation of JSON Web Signatures", + "main": "index.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "make test" + }, + "repository": { + "type": "git", + "url": "git://github.com/brianloveswords/node-jws.git" + }, + "keywords": [ + "jws", + "json", + "web", + "signatures" + ], + "author": { + "name": "Brian J Brennan" + }, + "license": "MIT", + "gitHead": "c0f6b27bcea5a2ad2e304d91c2e842e4076a6b03", + "dependencies": { + "base64url": "~1.0.4", + "jwa": "^1.1.2" + }, + "devDependencies": { + "semver": "^5.1.0", + "tape": "~2.14.0" + }, + "bugs": { + "url": "https://github.com/brianloveswords/node-jws/issues" + }, + "homepage": "https://github.com/brianloveswords/node-jws#readme", + "_id": "jws@3.1.3", + "_shasum": "b88f1b4581a2c5ee8813c06b3fdf90ea9b5c7e6c", + "_from": "jws@>=3.1.3 <4.0.0", + "_npmVersion": "3.3.12", + "_nodeVersion": "5.2.0", + "_npmUser": { + "name": "brianloveswords", + "email": "brianloveswords@gmail.com" + }, + "maintainers": [ + { + "name": "brianloveswords", + "email": "brianloveswords@gmail.com" + }, + { + "name": "stenington", + "email": "mikelarssonftw@gmail.com" + }, + { + "name": "omsmith", + "email": "owen@omsmith.ca" + } + ], + "dist": { + "shasum": "b88f1b4581a2c5ee8813c06b3fdf90ea9b5c7e6c", + "tarball": "https://registry.npmjs.org/jws/-/jws-3.1.3.tgz" + }, + "_npmOperationalInternal": { + "host": "packages-6-west.internal.npmjs.com", + "tmp": "tmp/jws-3.1.3.tgz_1455809983684_0.8235816163942218" + }, + "_resolved": "https://registry.npmjs.org/jws/-/jws-3.1.3.tgz" +}
@@ -0,0 +1,248 @@
+# node-jws [](http://travis-ci.org/brianloveswords/node-jws) + +An implementation of [JSON Web Signatures](http://self-issued.info/docs/draft-ietf-jose-json-web-signature.html). + +This was developed against `draft-ietf-jose-json-web-signature-08` and +implements the entire spec **except** X.509 Certificate Chain +signing/verifying (patches welcome). + +There are both syncronous (`jws.sign`, `jws.verify`) and streaming +(`jws.createSign`, `jws.createVerify`) APIs. + +# Install + +```bash +$ npm install jws +``` + +# Usage + +## jws.ALGORITHMS +Array of supported algorithms. The following algorithms are currently supported. + +alg Parameter Value | Digital Signature or MAC Algorithm +----------------|---------------------------- +HS256 | HMAC using SHA-256 hash algorithm +HS384 | HMAC using SHA-384 hash algorithm +HS512 | HMAC using SHA-512 hash algorithm +RS256 | RSASSA using SHA-256 hash algorithm +RS384 | RSASSA using SHA-384 hash algorithm +RS512 | RSASSA using SHA-512 hash algorithm +ES256 | ECDSA using P-256 curve and SHA-256 hash algorithm +ES384 | ECDSA using P-384 curve and SHA-384 hash algorithm +ES512 | ECDSA using P-521 curve and SHA-512 hash algorithm +none | No digital signature or MAC value included + + +## jws.sign(options) + +(Synchronous) Return a JSON Web Signature for a header and a payload. + +Options: + +* `header` +* `payload` +* `secret` or `privateKey` +* `encoding` (Optional, defaults to 'utf8') + +`header` must be an object with an `alg` property. `header.alg` must be +one a value found in `jws.ALGORITHMS`. See above for a table of +supported algorithms. + +If `payload` is not a buffer or a string, it will be coerced into a string +using `JSON.stringify`. + +Example + +```js +const signature = jws.sign({ + header: { alg: 'HS256' }, + payload: 'h. jon benjamin', + secret: 'has a van', +}); +``` + +## jws.verify(signature, algorithm, secretOrKey) + +(Synchronous) Returns`true` or `false` for whether a signature matches a +secret or key. + +`signature` is a JWS Signature. `header.alg` must be a value found in `jws.ALGORITHMS`. +See above for a table of supported algorithms. `secretOrKey` is a string or +buffer containing either the secret for HMAC algorithms, or the PEM +encoded public key for RSA and ECDSA. + +Note that the `"alg"` value from the signature header is ignored. + + +## jws.decode(signature) + +(Synchronous) Returns the decoded header, decoded payload, and signature +parts of the JWS Signature. + +Returns an object with three properties, e.g. +```js +{ header: { alg: 'HS256' }, + payload: 'h. jon benjamin', + signature: 'YOWPewyGHKu4Y_0M_vtlEnNlqmFOclqp4Hy6hVHfFT4' +} +``` + +## jws.createSign(options) +Returns a new SignStream object. + +Options: + +* `header` (required) +* `payload` +* `key` || `privateKey` || `secret` +* `encoding` (Optional, defaults to 'utf8') + +Other than `header`, all options expect a string or a buffer when the +value is known ahead of time, or a stream for convenience. +`key`/`privateKey`/`secret` may also be an object when using an encrypted +private key, see the [crypto documentation][encrypted-key-docs]. + +Example +```js + +// This... +jws.createSign({ + header: { alg: 'RS256' }, + privateKey: privateKeyStream, + payload: payloadStream, +}).on('done', function(signature) { + // ... +}); + +// is equivilant to this: +const signer = jws.createSign( + header: { alg: 'RS256' }, +); +privateKeyStream.pipe(signer.privateKey); +payloadStream.pipe(signer.payload); +signer.on('done', function(signature) { + // ... +}); +``` + +## jws.createVerify(options) +Returns a new VerifyStream object. + +Options: + +* `signature` +* `algorithm` +* `key` || `publicKey` || `secret` +* `encoding` (Optional, defaults to 'utf8') + +All options expect a string or a buffer when the value is known ahead of +time, or a stream for convenience. + +Example +```js + +// This... +jws.createVerify({ + publicKey: pubKeyStream, + signature: sigStream, +}).on('done', function(verified, obj) { + // ... +}); + +// is equivilant to this: +const verifier = jws.createVerify(); +pubKeyStream.pipe(verifier.publicKey); +sigStream.pipe(verifier.signature); +verifier.on('done', function(verified, obj) { + // ... +}); +``` + +## Class: SignStream +A `Readable Stream` that emits a single data event, the calculated +signature, when done. + +### Event: 'done' +`function (signature) { }` + +### signer.payload + +A `Writable Stream` that expects the JWS payload. Do *not* use if you +passed a `payload` option to the constructor. + +Example + +```js +payloadStream.pipe(signer.payload); +``` + +### signer.secret<br>signer.key<br>signer.privateKey + +A `Writable Stream`. Expects the JWS secret for HMAC, or the privateKey +for ECDSA and RSA. Do *not* use if you passed a `secret` or `key` option +to the constructor. + +Example: + +```js +privateKeyStream.pipe(signer.privateKey); +``` + +## Class: VerifyStream + +This is a `Readable Stream` that emits a single data event, the result +of whether or not that signature was valid. + +### Event: 'done' +`function (valid, obj) { }` + +`valid` is a boolean for whether or not the signature is valid. + +### verifier.signature +A `Writable Stream` that expects a JWS Signature. Do *not* use if you +passed a `signature` option to the constructor. + +### verifier.secret<br>verifier.key<br>verifier.publicKey + +A `Writable Stream` that expects a public key or secret. Do *not* use if you +passed a `key` or `secret` option to the constructor. + + +# TODO + +* It feels like there should be some convenience options/APIs for + defining the algorithm rather than having to define a header object + with `{ alg: 'ES512' }` or whatever every time. + +* X.509 support, ugh + + +# License + +MIT + +``` +Copyright (c) 2013-2015 Brian J. Brennan + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +``` + +[encrypted-key-docs]: https://nodejs.org/api/crypto.html#crypto_sign_sign_private_key_output_format
@@ -0,0 +1,321 @@
+/*global process*/ +const Buffer = require('buffer').Buffer; +const fs = require('fs'); +const test = require('tape'); +const jws = require('..'); + +const NODE_VERSION = require('semver').clean(process.version); +const SUPPORTS_ENCRYPTED_KEYS = require('semver').gte(NODE_VERSION, '0.11.8'); + +function readfile(path) { + return fs.readFileSync(__dirname + '/' + path).toString(); +} + +function readstream(path) { + return fs.createReadStream(__dirname + '/' + path); +} + +const rsaPrivateKey = readfile('rsa-private.pem'); +const rsaPrivateKeyEncrypted = readfile('rsa-private-encrypted.pem'); +const encryptedPassphrase = readfile('encrypted-key-passphrase'); +const rsaPublicKey = readfile('rsa-public.pem'); +const rsaWrongPublicKey = readfile('rsa-wrong-public.pem'); +const ecdsaPrivateKey = { + '256': readfile('ec256-private.pem'), + '384': readfile('ec384-private.pem'), + '512': readfile('ec512-private.pem'), +}; +const ecdsaPublicKey = { + '256': readfile('ec256-public.pem'), + '384': readfile('ec384-public.pem'), + '512': readfile('ec512-public.pem'), +}; +const ecdsaWrongPublicKey = { + '256': readfile('ec256-wrong-public.pem'), + '384': readfile('ec384-wrong-public.pem'), + '512': readfile('ec512-wrong-public.pem'), +}; + +const BITS = ['256', '384', '512']; +const CURVES = { + '256': '256', + '384': '384', + '512': '521', +}; + +const payloadString = 'oh ćhey José!: ¬˚∆ƒå¬ß…©…åˆø˙ˆø´∆¬˚µ…˚¬˜øå…ˆßøˆƒ˜¬'; +const payload = { + name: payloadString, + value: ['one', 2, 3] +}; + +BITS.forEach(function (bits) { + test('HMAC using SHA-'+bits+' hash algorithm', function (t) { + const alg = 'HS'+bits; + const header = { alg: alg, typ: 'JWT' }; + const secret = 'sup'; + const jwsObj = jws.sign({ + header: header, + payload: payload, + secret: secret, + encoding: 'utf8', + }); + const parts = jws.decode(jwsObj); + t.ok(jws.verify(jwsObj, alg, secret), 'should verify'); + t.notOk(jws.verify(jwsObj, alg, 'something else'), 'should not verify with non-matching secret'); + t.same(parts.payload, payload, 'should match payload'); + t.same(parts.header, header, 'should match header'); + t.end(); + }); +}); + +BITS.forEach(function (bits) { + test('RSASSA using SHA-'+bits+' hash algorithm', function (t) { + const alg = 'RS'+bits; + const header = { alg: alg }; + const privateKey = rsaPrivateKey; + const publicKey = rsaPublicKey; + const wrongPublicKey = rsaWrongPublicKey; + const jwsObj = jws.sign({ + header: header, + payload: payload, + privateKey: privateKey + }); + const parts = jws.decode(jwsObj, { json: true }); + t.ok(jws.verify(jwsObj, alg, publicKey), 'should verify'); + t.notOk(jws.verify(jwsObj, alg, wrongPublicKey), 'should not verify with non-matching public key'); + t.notOk(jws.verify(jwsObj, 'HS'+bits, publicKey), 'should not verify with non-matching algorithm'); + t.same(parts.payload, payload, 'should match payload'); + t.same(parts.header, header, 'should match header'); + t.end(); + }); +}); + +BITS.forEach(function (bits) { + const curve = CURVES[bits]; + test('ECDSA using P-'+curve+' curve and SHA-'+bits+' hash algorithm', function (t) { + const alg = 'ES'+bits; + const header = { alg: alg }; + const privateKey = ecdsaPrivateKey[bits]; + const publicKey = ecdsaPublicKey[bits]; + const wrongPublicKey = ecdsaWrongPublicKey[bits]; + const jwsObj = jws.sign({ + header: header, + payload: payloadString, + privateKey: privateKey + }); + const parts = jws.decode(jwsObj); + t.ok(jws.verify(jwsObj, alg, publicKey), 'should verify'); + t.notOk(jws.verify(jwsObj, alg, wrongPublicKey), 'should not verify with non-matching public key'); + t.notOk(jws.verify(jwsObj, 'HS'+bits, publicKey), 'should not verify with non-matching algorithm'); + t.same(parts.payload, payloadString, 'should match payload'); + t.same(parts.header, header, 'should match header'); + t.end(); + }); +}); + +test('No digital signature or MAC value included', function (t) { + const alg = 'none'; + const header = { alg: alg }; + const payload = 'oh hey José!'; + const jwsObj = jws.sign({ + header: header, + payload: payload, + }); + const parts = jws.decode(jwsObj); + t.ok(jws.verify(jwsObj, alg), 'should verify'); + t.ok(jws.verify(jwsObj, alg, 'anything'), 'should still verify'); + t.notOk(jws.verify(jwsObj, 'HS256', 'anything'), 'should not verify with non-matching algorithm'); + t.same(parts.payload, payload, 'should match payload'); + t.same(parts.header, header, 'should match header'); + t.end(); +}); + +test('Streaming sign: HMAC', function (t) { + const dataStream = readstream('data.txt'); + const secret = 'shhhhh'; + const sig = jws.createSign({ + header: { alg: 'HS256' }, + secret: secret + }); + dataStream.pipe(sig.payload); + sig.on('done', function (signature) { + t.ok(jws.verify(signature, 'HS256', secret), 'should verify'); + t.end(); + }); +}); + +test('Streaming sign: RSA', function (t) { + const dataStream = readstream('data.txt'); + const privateKeyStream = readstream('rsa-private.pem'); + const publicKey = rsaPublicKey; + const wrongPublicKey = rsaWrongPublicKey; + const sig = jws.createSign({ + header: { alg: 'RS256' }, + }); + dataStream.pipe(sig.payload); + + process.nextTick(function () { + privateKeyStream.pipe(sig.key); + }); + + sig.on('done', function (signature) { + t.ok(jws.verify(signature, 'RS256', publicKey), 'should verify'); + t.notOk(jws.verify(signature, 'RS256', wrongPublicKey), 'should not verify'); + t.same(jws.decode(signature).payload, readfile('data.txt'), 'got all the data'); + t.end(); + }); +}); + +test('Streaming sign: RSA, predefined streams', function (t) { + const dataStream = readstream('data.txt'); + const privateKeyStream = readstream('rsa-private.pem'); + const publicKey = rsaPublicKey; + const wrongPublicKey = rsaWrongPublicKey; + const sig = jws.createSign({ + header: { alg: 'RS256' }, + payload: dataStream, + privateKey: privateKeyStream + }); + sig.on('done', function (signature) { + t.ok(jws.verify(signature, 'RS256', publicKey), 'should verify'); + t.notOk(jws.verify(signature, 'RS256', wrongPublicKey), 'should not verify'); + t.same(jws.decode(signature).payload, readfile('data.txt'), 'got all the data'); + t.end(); + }); +}); + +test('Streaming verify: ECDSA', function (t) { + const dataStream = readstream('data.txt'); + const privateKeyStream = readstream('ec512-private.pem'); + const publicKeyStream = readstream('ec512-public.pem'); + const sigStream = jws.createSign({ + header: { alg: 'ES512' }, + payload: dataStream, + privateKey: privateKeyStream + }); + const verifier = jws.createVerify({algorithm: 'ES512'}); + sigStream.pipe(verifier.signature); + publicKeyStream.pipe(verifier.key); + verifier.on('done', function (valid) { + t.ok(valid, 'should verify'); + t.end(); + }); +}); + +test('Streaming verify: ECDSA, with invalid key', function (t) { + const dataStream = readstream('data.txt'); + const privateKeyStream = readstream('ec512-private.pem'); + const publicKeyStream = readstream('ec512-wrong-public.pem'); + const sigStream = jws.createSign({ + header: { alg: 'ES512' }, + payload: dataStream, + privateKey: privateKeyStream + }); + const verifier = jws.createVerify({ + algorithm: 'ES512', + signature: sigStream, + publicKey: publicKeyStream, + }); + verifier.on('done', function (valid) { + t.notOk(valid, 'should not verify'); + t.end(); + }); +}); + +test('Streaming verify: errors during verify should emit as "error"', function (t) { + const verifierShouldError = jws.createVerify({ + algorithm: 'ES512', + signature: 'a.b.c', // the short/invalid length signature will make jwa throw + publicKey: 'invalid-key-will-make-crypto-throw' + }); + + verifierShouldError.on('done', function () { + t.fail(); + t.end(); + }); + verifierShouldError.on('error', function () { + t.end() + }); +}); + +if (SUPPORTS_ENCRYPTED_KEYS) { + test('Signing: should accept an encrypted key', function (t) { + const alg = 'RS256'; + const signature = jws.sign({ + header: { alg: alg }, + payload: 'verifyme', + privateKey: { + key: rsaPrivateKeyEncrypted, + passphrase: encryptedPassphrase + } + }); + t.ok(jws.verify(signature, 'RS256', rsaPublicKey)); + t.end(); + }); + + test('Streaming sign: should accept an encrypted key', function (t) { + const alg = 'RS256'; + const signer = jws.createSign({ + header: { alg: alg }, + payload: 'verifyme', + privateKey: { + key: rsaPrivateKeyEncrypted, + passphrase: encryptedPassphrase + } + }); + const verifier = jws.createVerify({ + algorithm: alg, + signature: signer, + publicKey: rsaPublicKey + }); + verifier.on('done', function (verified) { + t.ok(verified); + t.end(); + }); + }); +} + +test('jws.decode: not a jws signature', function (t) { + t.same(jws.decode('some garbage string'), null); + t.same(jws.decode('http://sub.domain.org'), null); + t.end(); +}); + +test('jws.decode: with a bogus header ', function (t) { + const header = Buffer('oh hei José!').toString('base64'); + const payload = Buffer('sup').toString('base64'); + const sig = header + '.' + payload + '.'; + const parts = jws.decode(sig); + t.same(parts, null); + t.end(); +}); + +test('jws.verify: missing or invalid algorithm', function (t) { + const header = Buffer('{"something":"not an algo"}').toString('base64'); + const payload = Buffer('sup').toString('base64'); + const sig = header + '.' + payload + '.'; + try { jws.verify(sig) } + catch (e) { + t.same(e.code, 'MISSING_ALGORITHM'); + } + try { jws.verify(sig, 'whatever') } + catch (e) { + t.ok(e.message.match('"whatever" is not a valid algorithm.')); + } + t.end(); +}); + + +test('jws.isValid', function (t) { + const valid = jws.sign({ header: { alg: 'hs256' }, payload: 'hi', secret: 'shhh' }); + const invalid = (function(){ + const header = Buffer('oh hei José!').toString('base64'); + const payload = Buffer('sup').toString('base64'); + return header + '.' + payload + '.'; + })(); + t.same(jws.isValid('http://sub.domain.org'), false); + t.same(jws.isValid(invalid), false); + t.same(jws.isValid(valid), true); + t.end(); +});
@@ -0,0 +1,5 @@
+node_modules +test +History.md +Makefile +component.json
@@ -0,0 +1,66 @@
+ +0.7.1 / 2015-04-20 +================== + + * prevent extraordinary long inputs (@evilpacket) + * Fixed broken readme link + +0.7.0 / 2014-11-24 +================== + + * add time abbreviations, updated tests and readme for the new units + * fix example in the readme. + * add LICENSE file + +0.6.2 / 2013-12-05 +================== + + * Adding repository section to package.json to suppress warning from NPM. + +0.6.1 / 2013-05-10 +================== + + * fix singularization [visionmedia] + +0.6.0 / 2013-03-15 +================== + + * fix minutes + +0.5.1 / 2013-02-24 +================== + + * add component namespace + +0.5.0 / 2012-11-09 +================== + + * add short formatting as default and .long option + * add .license property to component.json + * add version to component.json + +0.4.0 / 2012-10-22 +================== + + * add rounding to fix crazy decimals + +0.3.0 / 2012-09-07 +================== + + * fix `ms(<String>)` [visionmedia] + +0.2.0 / 2012-09-03 +================== + + * add component.json [visionmedia] + * add days support [visionmedia] + * add hours support [visionmedia] + * add minutes support [visionmedia] + * add seconds support [visionmedia] + * add ms string support [visionmedia] + * refactor tests to facilitate ms(number) [visionmedia] + +0.1.0 / 2012-03-07 +================== + + * Initial release
@@ -0,0 +1,20 @@
+(The MIT License) + +Copyright (c) 2014 Guillermo Rauch <rauchg@gmail.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,35 @@
+# ms.js: miliseconds conversion utility + +```js +ms('2 days') // 172800000 +ms('1d') // 86400000 +ms('10h') // 36000000 +ms('2.5 hrs') // 9000000 +ms('2h') // 7200000 +ms('1m') // 60000 +ms('5s') // 5000 +ms('100') // 100 +``` + +```js +ms(60000) // "1m" +ms(2 * 60000) // "2m" +ms(ms('10 hours')) // "10h" +``` + +```js +ms(60000, { long: true }) // "1 minute" +ms(2 * 60000, { long: true }) // "2 minutes" +ms(ms('10 hours'), { long: true }) // "10 hours" +``` + +- Node/Browser compatible. Published as [`ms`](https://www.npmjs.org/package/ms) in [NPM](http://nodejs.org/download). +- If a number is supplied to `ms`, a string with a unit is returned. +- If a string that contains the number is supplied, it returns it as +a number (e.g: it returns `100` for `'100'`). +- If you pass a string with a number and a valid unit, the number of +equivalent ms is returned. + +## License + +MIT
@@ -0,0 +1,125 @@
+/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} options + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options){ + options = options || {}; + if ('string' == typeof val) return parse(val); + return options.long + ? long(val) + : short(val); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = '' + str; + if (str.length > 10000) return; + var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str); + if (!match) return; + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function short(ms) { + if (ms >= d) return Math.round(ms / d) + 'd'; + if (ms >= h) return Math.round(ms / h) + 'h'; + if (ms >= m) return Math.round(ms / m) + 'm'; + if (ms >= s) return Math.round(ms / s) + 's'; + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function long(ms) { + return plural(ms, d, 'day') + || plural(ms, h, 'hour') + || plural(ms, m, 'minute') + || plural(ms, s, 'second') + || ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, n, name) { + if (ms < n) return; + if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name; + return Math.ceil(ms / n) + ' ' + name + 's'; +}
@@ -0,0 +1,48 @@
+{ + "name": "ms", + "version": "0.7.1", + "description": "Tiny ms conversion utility", + "repository": { + "type": "git", + "url": "git://github.com/guille/ms.js.git" + }, + "main": "./index", + "devDependencies": { + "mocha": "*", + "expect.js": "*", + "serve": "*" + }, + "component": { + "scripts": { + "ms/index.js": "index.js" + } + }, + "gitHead": "713dcf26d9e6fd9dbc95affe7eff9783b7f1b909", + "bugs": { + "url": "https://github.com/guille/ms.js/issues" + }, + "homepage": "https://github.com/guille/ms.js", + "_id": "ms@0.7.1", + "scripts": {}, + "_shasum": "9cd13c03adbff25b65effde7ce864ee952017098", + "_from": "ms@>=0.7.1 <0.8.0", + "_npmVersion": "2.7.5", + "_nodeVersion": "0.12.2", + "_npmUser": { + "name": "rauchg", + "email": "rauchg@gmail.com" + }, + "maintainers": [ + { + "name": "rauchg", + "email": "rauchg@gmail.com" + } + ], + "dist": { + "shasum": "9cd13c03adbff25b65effde7ce864ee952017098", + "tarball": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,30 @@
+{ + "maxdepth": 4, + "maxstatements": 200, + "maxcomplexity": 12, + "maxlen": 80, + "maxparams": 5, + + "curly": true, + "eqeqeq": true, + "immed": true, + "latedef": false, + "noarg": true, + "noempty": true, + "nonew": true, + "undef": true, + "unused": "vars", + "trailing": true, + + "quotmark": true, + "expr": true, + "asi": true, + + "browser": false, + "esnext": true, + "devel": false, + "node": false, + "nonstandard": false, + + "predef": ["require", "module", "__dirname", "__filename"] +}
@@ -0,0 +1,19 @@
+Copyright (c) 2012-2014 Raynos. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.
@@ -0,0 +1,4 @@
+browser: + node ./support/compile + +.PHONY: browser
@@ -0,0 +1,32 @@
+# xtend + +[![browser support][3]][4] + +[](http://github.com/badges/stability-badges) + +Extend like a boss + +xtend is a basic utility library which allows you to extend an object by appending all of the properties from each object in a list. When there are identical properties, the right-most property takes precedence. + +## Examples + +```js +var extend = require("xtend") + +// extend returns a new object. Does not mutate arguments +var combination = extend({ + a: "a", + b: 'c' +}, { + b: "b" +}) +// { a: "a", b: "b" } +``` + +## Stability status: Locked + +## MIT Licenced + + + [3]: http://ci.testling.com/Raynos/xtend.png + [4]: http://ci.testling.com/Raynos/xtend
@@ -0,0 +1,19 @@
+module.exports = extend + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +function extend() { + var target = {} + + for (var i = 0; i < arguments.length; i++) { + var source = arguments[i] + + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + target[key] = source[key] + } + } + } + + return target +}
@@ -0,0 +1,17 @@
+module.exports = extend + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +function extend(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] + + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + target[key] = source[key] + } + } + } + + return target +}
@@ -0,0 +1,84 @@
+{ + "name": "xtend", + "version": "4.0.1", + "description": "extend like a boss", + "keywords": [ + "extend", + "merge", + "options", + "opts", + "object", + "array" + ], + "author": { + "name": "Raynos", + "email": "raynos2@gmail.com" + }, + "repository": { + "type": "git", + "url": "git://github.com/Raynos/xtend.git" + }, + "main": "immutable", + "scripts": { + "test": "node test" + }, + "dependencies": {}, + "devDependencies": { + "tape": "~1.1.0" + }, + "homepage": "https://github.com/Raynos/xtend", + "contributors": [ + { + "name": "Jake Verbaten" + }, + { + "name": "Matt Esch" + } + ], + "bugs": { + "url": "https://github.com/Raynos/xtend/issues", + "email": "raynos2@gmail.com" + }, + "license": "MIT", + "testling": { + "files": "test.js", + "browsers": [ + "ie/7..latest", + "firefox/16..latest", + "firefox/nightly", + "chrome/22..latest", + "chrome/canary", + "opera/12..latest", + "opera/next", + "safari/5.1..latest", + "ipad/6.0..latest", + "iphone/6.0..latest" + ] + }, + "engines": { + "node": ">=0.4" + }, + "gitHead": "23dc302a89756da89c1897bc732a752317e35390", + "_id": "xtend@4.0.1", + "_shasum": "a5c6d532be656e23db820efb943a1f04998d63af", + "_from": "xtend@>=4.0.1 <5.0.0", + "_npmVersion": "2.14.1", + "_nodeVersion": "0.10.32", + "_npmUser": { + "name": "raynos", + "email": "raynos2@gmail.com" + }, + "dist": { + "shasum": "a5c6d532be656e23db820efb943a1f04998d63af", + "tarball": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + }, + "maintainers": [ + { + "name": "raynos", + "email": "raynos2@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,83 @@
+var test = require("tape") +var extend = require("./") +var mutableExtend = require("./mutable") + +test("merge", function(assert) { + var a = { a: "foo" } + var b = { b: "bar" } + + assert.deepEqual(extend(a, b), { a: "foo", b: "bar" }) + assert.end() +}) + +test("replace", function(assert) { + var a = { a: "foo" } + var b = { a: "bar" } + + assert.deepEqual(extend(a, b), { a: "bar" }) + assert.end() +}) + +test("undefined", function(assert) { + var a = { a: undefined } + var b = { b: "foo" } + + assert.deepEqual(extend(a, b), { a: undefined, b: "foo" }) + assert.deepEqual(extend(b, a), { a: undefined, b: "foo" }) + assert.end() +}) + +test("handle 0", function(assert) { + var a = { a: "default" } + var b = { a: 0 } + + assert.deepEqual(extend(a, b), { a: 0 }) + assert.deepEqual(extend(b, a), { a: "default" }) + assert.end() +}) + +test("is immutable", function (assert) { + var record = {} + + extend(record, { foo: "bar" }) + assert.equal(record.foo, undefined) + assert.end() +}) + +test("null as argument", function (assert) { + var a = { foo: "bar" } + var b = null + var c = void 0 + + assert.deepEqual(extend(b, a, c), { foo: "bar" }) + assert.end() +}) + +test("mutable", function (assert) { + var a = { foo: "bar" } + + mutableExtend(a, { bar: "baz" }) + + assert.equal(a.bar, "baz") + assert.end() +}) + +test("null prototype", function(assert) { + var a = { a: "foo" } + var b = Object.create(null) + b.b = "bar"; + + assert.deepEqual(extend(a, b), { a: "foo", b: "bar" }) + assert.end() +}) + +test("null prototype mutable", function (assert) { + var a = { foo: "bar" } + var b = Object.create(null) + b.bar = "baz"; + + mutableExtend(a, b) + + assert.equal(a.bar, "baz") + assert.end() +})
@@ -0,0 +1,92 @@
+{ + "name": "jsonwebtoken", + "version": "7.1.6", + "description": "JSON Web Token implementation (symmetric and asymmetric)", + "main": "index.js", + "scripts": { + "test": "mocha --require test/util/fakeDate" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/auth0/node-jsonwebtoken.git" + }, + "keywords": [ + "jwt" + ], + "author": { + "name": "auth0" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/auth0/node-jsonwebtoken/issues" + }, + "dependencies": { + "cb": "^0.1.0", + "joi": "^6.10.1", + "jws": "^3.1.3", + "ms": "^0.7.1", + "xtend": "^4.0.1" + }, + "devDependencies": { + "atob": "^1.1.2", + "chai": "^1.10.0", + "conventional-changelog": "~1.1.0", + "mocha": "^2.1.0", + "sinon": "^1.15.4" + }, + "engines": { + "npm": ">=1.4.28", + "node": ">=0.12" + }, + "gitHead": "ae360b56792a875e16cefa8ff4103b87b4a2e386", + "homepage": "https://github.com/auth0/node-jsonwebtoken#readme", + "_id": "jsonwebtoken@7.1.6", + "_shasum": "2ea9557af144311148f53093cfeec69e1e048abc", + "_from": "jsonwebtoken@latest", + "_npmVersion": "2.15.1", + "_nodeVersion": "4.4.3", + "_npmUser": { + "name": "jfromaniello", + "email": "jfromaniello@gmail.com" + }, + "dist": { + "shasum": "2ea9557af144311148f53093cfeec69e1e048abc", + "tarball": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.1.6.tgz" + }, + "maintainers": [ + { + "name": "dschenkelman", + "email": "damian.schenkelman@gmail.com" + }, + { + "name": "iaco", + "email": "sebastian.iacomuzzi@gmail.com" + }, + { + "name": "jaredhanson", + "email": "jaredhanson@gmail.com" + }, + { + "name": "jfromaniello", + "email": "jfromaniello@gmail.com" + }, + { + "name": "pose", + "email": "albertopose@gmail.com" + }, + { + "name": "rolodato", + "email": "rlopezdato@gmail.com" + }, + { + "name": "woloski", + "email": "matiasw@gmail.com" + } + ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/jsonwebtoken-7.1.6.tgz_1468585972042_0.5801840056665242" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.1.6.tgz" +}
@@ -0,0 +1,146 @@
+var Joi = require('joi'); +var timespan = require('./lib/timespan'); +var xtend = require('xtend'); +var jws = require('jws'); +var cb = require('cb'); + +var sign_options_schema = Joi.object().keys({ + expiresIn: [Joi.number().integer(), Joi.string()], + notBefore: [Joi.number().integer(), Joi.string()], + audience: [Joi.string(), Joi.array()], + algorithm: Joi.string().valid('RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512', 'HS256', 'HS384', 'HS512', 'none'), + header: Joi.object(), + encoding: Joi.string(), + issuer: Joi.string(), + subject: Joi.string(), + jwtid: Joi.string(), + noTimestamp: Joi.boolean() +}); + +var registered_claims_schema = Joi.object().keys({ + iat: Joi.number(), + exp: Joi.number(), + nbf: Joi.number() +}).unknown(); + + +var options_to_payload = { + 'audience': 'aud', + 'issuer': 'iss', + 'subject': 'sub', + 'jwtid': 'jti' +}; + +var options_for_objects = [ + 'expiresIn', + 'notBefore', + 'noTimestamp', + 'audience', + 'issuer', + 'subject', + 'jwtid', +]; + +module.exports = function (payload, secretOrPrivateKey, options, callback) { + options = options || {}; + + var isObjectPayload = typeof payload === 'object' && + !Buffer.isBuffer(payload); + + var header = xtend({ + alg: options.algorithm || 'HS256', + typ: isObjectPayload ? 'JWT' : undefined + }, options.header); + + function failure(err) { + if (callback) { + return callback(err); + } + throw err; + } + + + if (typeof payload === 'undefined') { + return failure(new Error('payload is required')); + } else if (isObjectPayload) { + var payload_validation_result = registered_claims_schema.validate(payload); + + if (payload_validation_result.error) { + return failure(payload_validation_result.error); + } + + payload = xtend(payload); + } else { + var invalid_options = options_for_objects.filter(function (opt) { + return typeof options[opt] !== 'undefined'; + }); + + if (invalid_options.length > 0) { + return failure(new Error('invalid ' + invalid_options.join(',') + ' option for ' + (typeof payload ) + ' payload')); + } + } + + if (typeof payload.exp !== 'undefined' && typeof options.expiresIn !== 'undefined') { + return failure(new Error('Bad "options.expiresIn" option the payload already has an "exp" property.')); + } + + if (typeof payload.nbf !== 'undefined' && typeof options.notBefore !== 'undefined') { + return failure(new Error('Bad "options.notBefore" option the payload already has an "nbf" property.')); + } + + var validation_result = sign_options_schema.validate(options); + + if (validation_result.error) { + return failure(validation_result.error); + } + + var timestamp = payload.iat || Math.floor(Date.now() / 1000); + + if (!options.noTimestamp) { + payload.iat = timestamp; + } else { + delete payload.iat; + } + + if (typeof options.notBefore !== 'undefined') { + payload.nbf = timespan(options.notBefore); + if (typeof payload.nbf === 'undefined') { + return failure(new Error('"notBefore" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60')); + } + } + + if (typeof options.expiresIn !== 'undefined' && typeof payload === 'object') { + payload.exp = timespan(options.expiresIn, timestamp); + if (typeof payload.exp === 'undefined') { + return failure(new Error('"expiresIn" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60')); + } + } + + Object.keys(options_to_payload).forEach(function (key) { + var claim = options_to_payload[key]; + if (typeof options[key] !== 'undefined') { + if (typeof payload[claim] !== 'undefined') { + return failure(new Error('Bad "options.' + key + '" option. The payload already has an "' + claim + '" property.')); + } + payload[claim] = options[key]; + } + }); + + var encoding = options.encoding || 'utf8'; + + if (typeof callback === 'function') { + callback = callback && cb(callback).once(); + + jws.createSign({ + header: header, + privateKey: secretOrPrivateKey, + payload: payload, + encoding: encoding + }).once('error', callback) + .once('done', function (signature) { + callback(null, signature); + }); + } else { + return jws.sign({header: header, payload: payload, secret: secretOrPrivateKey, encoding: encoding}); + } +};
@@ -0,0 +1,60 @@
+var jwt = require('../index'); +var expect = require('chai').expect; +var jws = require('jws'); + +describe('signing a token asynchronously', function() { + + describe('when signing a token', function() { + var secret = 'shhhhhh'; + + it('should return the same result as singing synchronously', function(done) { + jwt.sign({ foo: 'bar' }, secret, { algorithm: 'HS256' }, function (err, asyncToken) { + if (err) return done(err); + var syncToken = jwt.sign({ foo: 'bar' }, secret, { algorithm: 'HS256' }); + expect(asyncToken).to.be.a('string'); + expect(asyncToken.split('.')).to.have.length(3); + expect(asyncToken).to.equal(syncToken); + done(); + }); + }); + + it('should work', function (done) { + jwt.sign({abc: 1}, "secret", {}, function (err, res) { + expect(err).to.be.null(); + done(); + }); + }); + + it('should return error when secret is not a cert for RS256', function(done) { + //this throw an error because the secret is not a cert and RS256 requires a cert. + jwt.sign({ foo: 'bar' }, secret, { algorithm: 'RS256' }, function (err) { + expect(err).to.be.ok(); + done(); + }); + }); + + it('should return error on wrong arguments', function(done) { + //this throw an error because the secret is not a cert and RS256 requires a cert. + jwt.sign({ foo: 'bar' }, secret, { notBefore: {} }, function (err) { + expect(err).to.be.ok(); + done(); + }); + }); + + it('should return error on wrong arguments (2)', function(done) { + jwt.sign('string', 'secret', {noTimestamp: true}, function (err) { + expect(err).to.be.ok(); + expect(err).to.be.instanceof(Error); + done(); + }); + }); + + it('should not stringify the payload', function (done) { + jwt.sign('string', 'secret', {}, function (err, token) { + if (err) { return done(err); } + expect(jws.decode(token).payload).to.equal('string'); + done(); + }); + }); + }); +});
@@ -0,0 +1,10 @@
+var jwt = require("../."); +var assert = require('chai').assert; + +describe('buffer payload', function () { + it('should work', function () { + var payload = new Buffer('TkJyotZe8NFpgdfnmgINqg==', 'base64'); + var token = jwt.sign(payload, "signing key"); + assert.equal(jwt.decode(token), payload.toString()); + }); +});
@@ -0,0 +1,37 @@
+var jwt = require('../index'); +var expect = require('chai').expect; +var atob = require('atob'); + +describe('encoding', function() { + + function b64_to_utf8 (str) { + return decodeURIComponent(escape(atob( str ))); + } + + it('should properly encode the token (utf8)', function () { + var expected = 'José'; + var token = jwt.sign({ name: expected }, 'shhhhh'); + var decoded_name = JSON.parse(b64_to_utf8(token.split('.')[1])).name; + expect(decoded_name).to.equal(expected); + }); + + it('should properly encode the token (binary)', function () { + var expected = 'José'; + var token = jwt.sign({ name: expected }, 'shhhhh', { encoding: 'binary' }); + var decoded_name = JSON.parse(atob(token.split('.')[1])).name; + expect(decoded_name).to.equal(expected); + }); + + it('should return the same result when decoding', function () { + var username = '測試'; + + var token = jwt.sign({ + username: username + }, 'test'); + + var payload = jwt.verify(token, 'test'); + + expect(payload.username).to.equal(username); + }); + +});
@@ -0,0 +1,53 @@
+var jwt = require('../index'); +var expect = require('chai').expect; + +describe('expires option', function() { + + it('should work with a number of seconds', function () { + var token = jwt.sign({foo: 123}, '123', { expiresIn: 10 }); + var result = jwt.verify(token, '123'); + expect(result.exp).to.be.closeTo(Math.floor(Date.now() / 1000) + 10, 0.2); + }); + + it('should work with a string', function () { + var token = jwt.sign({foo: 123}, '123', { expiresIn: '2d' }); + var result = jwt.verify(token, '123'); + var two_days_in_secs = 2 * 24 * 60 * 60; + expect(result.exp).to.be.closeTo(Math.floor(Date.now() / 1000) + two_days_in_secs, 0.2); + }); + + it('should work with a string second example', function () { + var token = jwt.sign({foo: 123}, '123', { expiresIn: '36h' }); + var result = jwt.verify(token, '123'); + var day_and_a_half_in_secs = 1.5 * 24 * 60 * 60; + expect(result.exp).to.be.closeTo(Math.floor(Date.now() / 1000) + day_and_a_half_in_secs, 0.2); + }); + + + it('should throw if expires has a bad string format', function () { + expect(function () { + jwt.sign({foo: 123}, '123', { expiresIn: '1 monkey' }); + }).to.throw(/"expiresIn" should be a number of seconds or string representing a timespan/); + }); + + it('should throw if expires is not an string or number', function () { + expect(function () { + jwt.sign({foo: 123}, '123', { expiresIn: { crazy : 213 } }); + }).to.throw(/"expiresIn" must be a number/); + }); + + it('should throw an error if expiresIn and exp are provided', function () { + expect(function () { + jwt.sign({ foo: 123, exp: 839218392183 }, '123', { expiresIn: '5h' }); + }).to.throw(/Bad "options.expiresIn" option the payload already has an "exp" property./); + }); + + + it('should throw on deprecated expiresInSeconds option', function () { + expect(function () { + jwt.sign({foo: 123}, '123', { expiresInSeconds: 5 }); + }).to.throw('"expiresInSeconds" is not allowed'); + }); + + +});
@@ -0,0 +1,22 @@
+var jwt = require('../index'); +var expect = require('chai').expect; + +describe('iat', function () { + + it('should work with a exp calculated based on numeric iat', function () { + var dateNow = Math.floor(Date.now() / 1000); + var iat = dateNow - 30; + var expiresIn = 50; + var token = jwt.sign({foo: 123, iat: iat}, '123', {expiresIn: expiresIn}); + var result = jwt.verify(token, '123'); + expect(result.exp).to.be.closeTo(iat + expiresIn, 0.2); + }); + + + it('should throw if iat is not a number', function () { + expect(function () { + jwt.sign({foo: 123, iat: 'hello'}, '123'); + }).to.throw(/"iat" must be a number/); + }); + +});
@@ -0,0 +1,58 @@
+var jwt = require('../index'); +var expect = require('chai').expect; +var assert = require('chai').assert; + +describe('invalid expiration', function() { + + it('should fail with string', function (done) { + var broken_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxMjMiLCJmb28iOiJhZGFzIn0.cDa81le-pnwJMcJi3o3PBwB7cTJMiXCkizIhxbXAKRg'; + + jwt.verify(broken_token, '123', function (err, decoded) { + expect(err.name).to.equal('JsonWebTokenError'); + done(); + }); + + }); + + it('should fail with 0', function (done) { + var broken_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjAsImZvbyI6ImFkYXMifQ.UKxix5T79WwfqAA0fLZr6UrhU-jMES2unwCOFa4grEA'; + + jwt.verify(broken_token, '123', function (err) { + expect(err.name).to.equal('TokenExpiredError'); + done(); + }); + + }); + + it('should fail with false', function (done) { + var broken_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOmZhbHNlLCJmb28iOiJhZGFzIn0.iBn33Plwhp-ZFXqppCd8YtED77dwWU0h68QS_nEQL8I'; + + jwt.verify(broken_token, '123', function (err) { + expect(err.name).to.equal('JsonWebTokenError'); + done(); + }); + + }); + + it('should fail with true', function (done) { + var broken_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOnRydWUsImZvbyI6ImFkYXMifQ.eOWfZCTM5CNYHAKSdFzzk2tDkPQmRT17yqllO-ItIMM'; + + jwt.verify(broken_token, '123', function (err) { + expect(err.name).to.equal('JsonWebTokenError'); + done(); + }); + + }); + + it('should fail with object', function (done) { + var broken_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOnt9LCJmb28iOiJhZGFzIn0.1JjCTsWLJ2DF-CfESjLdLfKutUt3Ji9cC7ESlcoBHSY'; + + jwt.verify(broken_token, '123', function (err) { + expect(err.name).to.equal('JsonWebTokenError'); + done(); + }); + + }); + + +});
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE----- +MIIDJjCCAg6gAwIBAgIJAMyz3mSPlaW4MA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV +BAMUCyouYXV0aDAuY29tMB4XDTEzMDQxODE3MDE1MFoXDTI2MTIyNjE3MDE1MFow +FjEUMBIGA1UEAxQLKi5hdXRoMC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDZq1Ua0/BGm+TaBFoftKWeYMWrQG9Fx3g7ikErxljmyOvlwqkiat3q +ixX+Dxw9TFb5gbBjNJ+L3nt4YefJgLsYvsHqkOUxWsB+HM/ulJRVnVrZm1tI3Nbg +xO1BQ7DrGfBpq2KCxtQCaQFRlQJw1+qS5LwrdIvihB7Kc142VElCFFHJ6+09eMUy +jy00Z5pfQr4Am6W6eEOS9ObDbNs4XgKOcWe5khWXj3UStou+VgbAg40XcYht2IbY +gMfKF+VUZOy3+e+aRTqPOBU3MAeb0tvCCPUQJbNAUHgSKVhAvNf8mRwttVsOLT70 +anjjeCOd7RKS8fVKBwc2KtgNkghYdPY9AgMBAAGjdzB1MB0GA1UdDgQWBBSi4+X0 ++MvCKDdd375mDhx/ZBbJ4DBGBgNVHSMEPzA9gBSi4+X0+MvCKDdd375mDhx/ZBbJ +4KEapBgwFjEUMBIGA1UEAxQLKi5hdXRoMC5jb22CCQDMs95kj5WluDAMBgNVHRME +BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBi0qPe0DzlPSufq+Gdk2Fwf1pGEtjA +D34IxxJ9SX6r1DS/NIP7IOLUnNU8cP8BQWl7i413v29jJsNV457pjdmqf8J7OE9O +eF5Yz1x91gY/27561Iga/TQeIVOlFQAgx66eLfUFFoAig3hz2srZo5TzYBixMJsS +fYMXHPiU7KoLUqYXvpSXIllstQCu51KCC6t9H7wZ92lTES1v76hFY4edQ30sftPo +kjAYWGEhMjPo/r4THcdSMqKXoRtCGEun4pTXid7MJcTgdGDrAJddLWi6SxKecEVB +MhMu4XfUCdxCwqQPjHeJ+zE49A1CUdBB2FN3BNLbmTTwEBgmuwyGRzhj +-----END CERTIFICATE-----
@@ -0,0 +1,12 @@
+var jwt = require('../index'); +var expect = require('chai').expect; + +describe('issue 147 - signing with a sealed payload', function() { + + it('should put the expiration claim', function () { + var token = jwt.sign(Object.seal({foo: 123}), '123', { expiresIn: 10 }); + var result = jwt.verify(token, '123'); + expect(result.exp).to.be.closeTo(Math.floor(Date.now() / 1000) + 10, 0.2); + }); + +});
@@ -0,0 +1,15 @@
+var expect = require('chai').expect; +var jwt = require('./..'); +var atob = require('atob'); + +describe('issue 196', function () { + function b64_to_utf8 (str) { + return decodeURIComponent(escape(atob( str ))); + } + + it('should use issuer provided in payload.iss', function () { + var token = jwt.sign({ iss: 'foo' }, 'shhhhh'); + var decoded_issuer = JSON.parse(b64_to_utf8(token.split('.')[1])).iss; + expect(decoded_issuer).to.equal('foo'); + }); +});
@@ -0,0 +1,15 @@
+var jwt = require('../'); + +describe('issue 70 - public key start with BEING PUBLIC KEY', function () { + + it('should work', function (done) { + var fs = require('fs'); + var cert_pub = fs.readFileSync(__dirname + '/rsa-public.pem'); + var cert_priv = fs.readFileSync(__dirname + '/rsa-private.pem'); + + var token = jwt.sign({ foo: 'bar' }, cert_priv, { algorithm: 'RS256'}); + + jwt.verify(token, cert_pub, done); + }); + +});
@@ -0,0 +1,82 @@
+var jwt = require('../index'); + +var expect = require('chai').expect; +var assert = require('chai').assert; + +describe('HS256', function() { + + describe('when signing a token', function() { + var secret = 'shhhhhh'; + + var token = jwt.sign({ foo: 'bar' }, secret, { algorithm: 'HS256' }); + + it('should be syntactically valid', function() { + expect(token).to.be.a('string'); + expect(token.split('.')).to.have.length(3); + }); + + it('should without options', function(done) { + var callback = function(err, decoded) { + assert.ok(decoded.foo); + assert.equal('bar', decoded.foo); + done(); + }; + callback.issuer = "shouldn't affect"; + jwt.verify(token, secret, callback ); + }); + + it('should validate with secret', function(done) { + jwt.verify(token, secret, function(err, decoded) { + assert.ok(decoded.foo); + assert.equal('bar', decoded.foo); + done(); + }); + }); + + it('should throw with invalid secret', function(done) { + jwt.verify(token, 'invalid secret', function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + done(); + }); + }); + + it('should throw with secret and token not signed', function(done) { + var signed = jwt.sign({ foo: 'bar' }, secret, { algorithm: 'none' }); + var unsigned = signed.split('.')[0] + '.' + signed.split('.')[1] + '.'; + jwt.verify(unsigned, 'secret', function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + done(); + }); + }); + + it('should throw when verifying null', function(done) { + jwt.verify(null, 'secret', function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + done(); + }); + }); + + it('should return an error when the token is expired', function(done) { + var token = jwt.sign({ exp: 1 }, secret, { algorithm: 'HS256' }); + jwt.verify(token, secret, { algorithm: 'HS256' }, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + done(); + }); + }); + + it('should NOT return an error when the token is expired with "ignoreExpiration"', function(done) { + var token = jwt.sign({ exp: 1, foo: 'bar' }, secret, { algorithm: 'HS256' }); + jwt.verify(token, secret, { algorithm: 'HS256', ignoreExpiration: true }, function(err, decoded) { + assert.ok(decoded.foo); + assert.equal('bar', decoded.foo); + assert.isNull(err); + done(); + }); + }); + + }); +});
@@ -0,0 +1,423 @@
+var jwt = require('../index'); +var fs = require('fs'); +var path = require('path'); + +var expect = require('chai').expect; +var assert = require('chai').assert; +var ms = require('ms'); + +describe('RS256', function() { + var pub = fs.readFileSync(path.join(__dirname, 'pub.pem')); + var priv = fs.readFileSync(path.join(__dirname, 'priv.pem')); + var invalid_pub = fs.readFileSync(path.join(__dirname, 'invalid_pub.pem')); + + describe('when signing a token', function() { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' }); + + it('should be syntactically valid', function() { + expect(token).to.be.a('string'); + expect(token.split('.')).to.have.length(3); + }); + + context('asynchronous', function() { + it('should validate with public key', function(done) { + jwt.verify(token, pub, function(err, decoded) { + assert.ok(decoded.foo); + assert.equal('bar', decoded.foo); + done(); + }); + }); + + it('should throw with invalid public key', function(done) { + jwt.verify(token, invalid_pub, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + done(); + }); + }); + }); + + context('synchronous', function() { + it('should validate with public key', function() { + var decoded = jwt.verify(token, pub); + assert.ok(decoded.foo); + assert.equal('bar', decoded.foo); + }); + + it('should throw with invalid public key', function() { + var jwtVerify = jwt.verify.bind(null, token, invalid_pub) + assert.throw(jwtVerify, 'invalid signature'); + }); + }); + + }); + + describe('when signing a token with expiration', function() { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', expiresIn: '10m' }); + + it('should be valid expiration', function(done) { + jwt.verify(token, pub, function(err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should be invalid', function(done) { + // expired token + token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', expiresIn: -1 * ms('10m') }); + + jwt.verify(token, pub, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'TokenExpiredError'); + assert.instanceOf(err.expiredAt, Date); + assert.instanceOf(err, jwt.TokenExpiredError); + done(); + }); + }); + + it('should NOT be invalid', function(done) { + // expired token + token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', expiresIn: -1 * ms('10m') }); + + jwt.verify(token, pub, { ignoreExpiration: true }, function(err, decoded) { + assert.ok(decoded.foo); + assert.equal('bar', decoded.foo); + done(); + }); + }); + }); + + describe('when signing a token with not before', function() { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', notBefore: -10 * 3600 }); + + it('should be valid expiration', function(done) { + jwt.verify(token, pub, function(err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should be invalid', function(done) { + // not active token + token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', notBefore: '10m' }); + + jwt.verify(token, pub, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'NotBeforeError'); + assert.instanceOf(err.date, Date); + assert.instanceOf(err, jwt.NotBeforeError); + done(); + }); + }); + + + it('should valid when date are equals', function(done) { + Date.fix(1451908031); + + token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', notBefore: 0 }); + + jwt.verify(token, pub, function(err, decoded) { + assert.isNull(err); + assert.isNotNull(decoded); + Date.unfix(); + done(); + }); + }); + + it('should NOT be invalid', function(done) { + // not active token + token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', notBefore: '10m' }); + + jwt.verify(token, pub, { ignoreNotBefore: true }, function(err, decoded) { + assert.ok(decoded.foo); + assert.equal('bar', decoded.foo); + done(); + }); + }); + }); + + describe('when signing a token with audience', function() { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', audience: 'urn:foo' }); + + it('should check audience', function(done) { + jwt.verify(token, pub, { audience: 'urn:foo' }, function(err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should check audience in array', function(done) { + jwt.verify(token, pub, { audience: ['urn:foo', 'urn:other'] }, function (err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should throw when invalid audience', function(done) { + jwt.verify(token, pub, { audience: 'urn:wrong' }, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + + it('should throw when invalid audience in array', function(done) { + jwt.verify(token, pub, { audience: ['urn:wrong', 'urn:morewrong'] }, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + + }); + + describe('when signing a token with array audience', function() { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', audience: [ 'urn:foo', 'urn:bar' ] }); + + it('should check audience', function(done) { + jwt.verify(token, pub, { audience: 'urn:foo' }, function(err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should check other audience', function(done) { + jwt.verify(token, pub, { audience: 'urn:bar' }, function(err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should check audience in array', function(done) { + jwt.verify(token, pub, { audience: ['urn:foo', 'urn:other'] }, function (err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should throw when invalid audience', function(done) { + jwt.verify(token, pub, { audience: 'urn:wrong' }, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + + it('should throw when invalid audience in array', function(done) { + jwt.verify(token, pub, { audience: ['urn:wrong', 'urn:morewrong'] }, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + + }); + + describe('when signing a token without audience', function() { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' }); + + it('should check audience', function(done) { + jwt.verify(token, pub, { audience: 'urn:wrong' }, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + + it('should check audience in array', function(done) { + jwt.verify(token, pub, { audience: ['urn:wrong', 'urn:morewrong'] }, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + + }); + + describe('when signing a token with issuer', function() { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', issuer: 'urn:foo' }); + + it('should check issuer', function(done) { + jwt.verify(token, pub, { issuer: 'urn:foo' }, function(err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should check the issuer when providing a list of valid issuers', function(done) { + jwt.verify(token, pub, { issuer: [ 'urn:foo', 'urn:bar' ] }, function(err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should throw when invalid issuer', function(done) { + jwt.verify(token, pub, { issuer: 'urn:wrong' }, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + }); + + describe('when signing a token without issuer', function() { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' }); + + it('should check issuer', function(done) { + jwt.verify(token, pub, { issuer: 'urn:foo' }, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + }); + + describe('when signing a token with subject', function() { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', subject: 'subject' }); + + it('should check subject', function(done) { + jwt.verify(token, pub, { subject: 'subject' }, function(err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should throw when invalid subject', function(done) { + jwt.verify(token, pub, { subject: 'wrongSubject' }, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + }); + + describe('when signing a token without subject', function() { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' }); + + it('should check subject', function(done) { + jwt.verify(token, pub, { subject: 'subject' }, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + }); + + describe('when signing a token with jwt id', function() { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256', jwtid: 'jwtid' }); + + it('should check jwt id', function(done) { + jwt.verify(token, pub, { jwtid: 'jwtid' }, function(err, decoded) { + assert.isNotNull(decoded); + assert.isNull(err); + done(); + }); + }); + + it('should throw when invalid jwt id', function(done) { + jwt.verify(token, pub, { jwtid: 'wrongJwtid' }, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + }); + + describe('when signing a token without jwt id', function() { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' }); + + it('should check jwt id', function(done) { + jwt.verify(token, pub, { jwtid: 'jwtid' }, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + assert.instanceOf(err, jwt.JsonWebTokenError); + done(); + }); + }); + }); + + describe('when verifying a malformed token', function() { + it('should throw', function(done) { + jwt.verify('fruit.fruit.fruit', pub, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + assert.equal(err.name, 'JsonWebTokenError'); + done(); + }); + }); + }); + + describe('when decoding a jwt token with additional parts', function() { + var token = jwt.sign({ foo: 'bar' }, priv, { algorithm: 'RS256' }); + + it('should throw', function(done) { + jwt.verify(token + '.foo', pub, function(err, decoded) { + assert.isUndefined(decoded); + assert.isNotNull(err); + done(); + }); + }); + }); + + describe('when decoding a invalid jwt token', function() { + it('should return null', function(done) { + var payload = jwt.decode('whatever.token'); + assert.isNull(payload); + done(); + }); + }); + + describe('when decoding a valid jwt token', function() { + it('should return the payload', function(done) { + var obj = { foo: 'bar' }; + var token = jwt.sign(obj, priv, { algorithm: 'RS256' }); + var payload = jwt.decode(token); + assert.equal(payload.foo, obj.foo); + done(); + }); + it('should return the header and payload and signature if complete option is set', function(done) { + var obj = { foo: 'bar' }; + var token = jwt.sign(obj, priv, { algorithm: 'RS256' }); + var decoded = jwt.decode(token, { complete: true }); + assert.equal(decoded.payload.foo, obj.foo); + assert.deepEqual(decoded.header, { typ: 'JWT', alg: 'RS256' }); + assert.ok(typeof decoded.signature == 'string'); + done(); + }); + }); +});
@@ -0,0 +1,12 @@
+var jwt = require('../index'); +var expect = require('chai').expect; + +describe('noTimestamp', function() { + + it('should work with string', function () { + var token = jwt.sign({foo: 123}, '123', { expiresIn: '5m' , noTimestamp: true }); + var result = jwt.verify(token, '123'); + expect(result.exp).to.be.closeTo(Math.floor(Date.now() / 1000) + (5*60), 0.5); + }); + +});
@@ -0,0 +1,33 @@
+var jwt = require('../index'); +var expect = require('chai').expect; +var JsonWebTokenError = require('../lib/JsonWebTokenError'); + +describe('non_object_values values', function() { + + it('should work with string', function () { + var token = jwt.sign('hello', '123'); + var result = jwt.verify(token, '123'); + expect(result).to.equal('hello'); + }); + + //v6 version will throw in this case: + it('should throw with expiresIn', function () { + expect(function () { + jwt.sign('hello', '123', { expiresIn: '12h' }); + }).to.throw(/invalid expiresIn option for string payload/); + }); + + it('should fail to validate audience when the payload is string', function () { + var token = jwt.sign('hello', '123'); + expect(function () { + jwt.verify(token, '123', { audience: 'foo' }); + }).to.throw(JsonWebTokenError); + }); + + it('should work with number', function () { + var token = jwt.sign(123, '123'); + var result = jwt.verify(token, '123'); + expect(result).to.equal('123'); + }); + +});
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAvtH4wKLYlIXZlfYQFJtXZVC3fD8XMarzwvb/fHUyJ6NvNStN ++H7GHp3/QhZbSaRyqK5hu5xXtFLgnI0QG8oE1NlXbczjH45LeHWhPIdc2uHSpzXi +c78kOugMY1vng4J10PF6+T2FNaiv0iXeIQq9xbwwPYpflViQyJnzGCIZ7VGan6Gb +RKzyTKcB58yx24pJq+CviLXEY52TIW1l5imcjGvLtlCp1za9qBZa4XGoVqHi1kRX +kdDSHty6lZWj3KxoRvTbiaBCH+75U7rifS6fR9lqjWE57bCGoz7+BBu9YmPKtI1K +kyHFqWpxaJc/AKf9xgg+UumeqVcirUmAsHJrMwIDAQABAoIBAQCYKw05YSNhXVPk +eHLeW/pXuwR3OkCexPrakOmwMC0s2vIF7mChN0d6hvhVlUp68X7V8SnS2JxAGo8v +iHY+Et3DdwZ3cxnzwh+BEhzgDfoIOmkoGppZPyX/K6klWtbGUrTtSISOWXbvEXQU +G0qGAvDOzIGTsdMDX7slnU70Ac23JybPY5qBSiE+ky8U4dm2fUHMroWub4QP5vA/ +nqyWqX2FB/MEAbcujaknDQrFCtbmtUYlBbJCKGd9V3cGEqp6H7oH+ah2ofMc91gJ +mCHk3YyWZB/bcVXH3CA+s1ywvCOVDBZ3Nw7Pt9zIcv6Rl9UKIy+Nx0QjXxR90Hla +Tr0GHIShAoGBAPsD7uXm+0ksnGyKRYgvlVad8Z8FUFT6bf4B+vboDbx40FO8O/5V +PraBPC5z8YRSBOQ/WfccPQzakkA28F2pXlRpXu5JcErVWnyyUiKpX5sw6iPenQR2 +JO9hY/GFbKiwUhVHpvWMcXFqFLSQu2A86jPnFFEfG48ZT4IhTzINKJVZAoGBAMKc +B3YGfVfY9qiRFXzYRdSRLg5c8p/HzuWwXc9vfJ4kQTDkPXe/+nqD67rzeT54uVec +jKoIrsCu4BfEaoyvOT+1KmUfdEpBgYZuuEC4CZf7dgKbXOpPVvZDMyJ/e7HyqTpw +mvIYJLPm2fNAcAsnbrNX5mhLwwzEIltbplUUeRdrAoGBAKhZgPYsLkhrZRXevreR +wkTvdUfD1pbHxtFfHqROCjhnhsFCM7JmFcNtdaFqHYczQxiZ7IqxI7jlNsVek2Md +3qgaa5LBKlDmOuP67N9WXUrGSaJ5ATIm0qrB1Lf9VlzktIiVH8L7yHHaRby8fQ8U +i7b3ukaV6HPW895A3M6iyJ8xAoGAInp4S+3MaTL0SFsj/nFmtcle6oaHKc3BlyoP +BMBQyMfNkPbu+PdXTjtvGTknouzKkX4X4cwWAec5ppxS8EffEa1sLGxNMxa19vZI +yJaShI21k7Ko3I5f7tNrDNKfPKCsYMEwgnHKluDwfktNTnyW/Uk2dgXuMaXSHHN5 +XZt59K8CgYArGVOWK7LUmf3dkTIs3tXBm4/IMtUZmWmcP9C8Xe/Dg/IdQhK5CIx4 +VXl8rgZNeX/5/4nJ8Q3LrdLau1Iz620trNRGU6sGMs3x4WQbSq93RRbFzfG1oK74 +IOo5yIBxImQOSk5jz31gF9RJb15SDBIxonuWv8qAERyUfvrmEwR0kg== +-----END RSA PRIVATE KEY-----
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIJAMKR/NsyfcazMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTIxMTEyMjM0MzQxWhcNMTYxMjIxMjM0MzQxWjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAvtH4wKLYlIXZlfYQFJtXZVC3fD8XMarzwvb/fHUyJ6NvNStN+H7GHp3/ +QhZbSaRyqK5hu5xXtFLgnI0QG8oE1NlXbczjH45LeHWhPIdc2uHSpzXic78kOugM +Y1vng4J10PF6+T2FNaiv0iXeIQq9xbwwPYpflViQyJnzGCIZ7VGan6GbRKzyTKcB +58yx24pJq+CviLXEY52TIW1l5imcjGvLtlCp1za9qBZa4XGoVqHi1kRXkdDSHty6 +lZWj3KxoRvTbiaBCH+75U7rifS6fR9lqjWE57bCGoz7+BBu9YmPKtI1KkyHFqWpx +aJc/AKf9xgg+UumeqVcirUmAsHJrMwIDAQABo4GnMIGkMB0GA1UdDgQWBBTs83nk +LtoXFlmBUts3EIxcVvkvcjB1BgNVHSMEbjBsgBTs83nkLtoXFlmBUts3EIxcVvkv +cqFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV +BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAMKR/NsyfcazMAwGA1UdEwQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBABw7w/5k4d5dVDgd/OOOmXdaaCIKvt7d +3ntlv1SSvAoKT8d8lt97Dm5RrmefBI13I2yivZg5bfTge4+vAV6VdLFdWeFp1b/F +OZkYUv6A8o5HW0OWQYVX26zIqBcG2Qrm3reiSl5BLvpj1WSpCsYvs5kaO4vFpMak +/ICgdZD+rxwxf8Vb/6fntKywWSLgwKH3mJ+Z0kRlpq1g1oieiOm1/gpZ35s0Yuor +XZba9ptfLCYSggg/qc3d3d0tbHplKYkwFm7f5ORGHDSD5SJm+gI7RPE+4bO8q79R +PAfbG1UGuJ0b/oigagciHhJp851SQRYf3JuNSc17BnK2L5IEtzjqr+Q= +-----END CERTIFICATE-----
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAvzoCEC2rpSpJQaWZbUmlsDNwp83Jr4fi6KmBWIwnj1MZ6CUQ +7rBasuLI8AcfX5/10scSfQNCsTLV2tMKQaHuvyrVfwY0dINk+nkqB74QcT2oCCH9 +XduJjDuwWA4xLqAKuF96FsIes52opEM50W7/W7DZCKXkC8fFPFj6QF5ZzApDw2Qs +u3yMRmr7/W9uWeaTwfPx24YdY7Ah+fdLy3KN40vXv9c4xiSafVvnx9BwYL7H1Q8N +iK9LGEN6+JSWfgckQCs6UUBOXSZdreNN9zbQCwyzee7bOJqXUDAuLcFARzPw1EsZ +AyjVtGCKIQ0/btqK+jFunT2NBC8RItanDZpptQIDAQABAoIBAQCsssO4Pra8hFMC +gX7tr0x+tAYy1ewmpW8stiDFilYT33YPLKJ9HjHbSms0MwqHftwwTm8JDc/GXmW6 +qUui+I64gQOtIzpuW1fvyUtHEMSisI83QRMkF6fCSQm6jJ6oQAtOdZO6R/gYOPNb +3gayeS8PbMilQcSRSwp6tNTVGyC33p43uUUKAKHnpvAwUSc61aVOtw2wkD062XzM +hJjYpHm65i4V31AzXo8HF42NrAtZ8K/AuQZne5F/6F4QFVlMKzUoHkSUnTp60XZx +X77GuyDeDmCgSc2J7xvR5o6VpjsHMo3ek0gJk5ZBnTgkHvnpbULCRxTmDfjeVPue +v3NN2TBFAoGBAPxbqNEsXPOckGTvG3tUOAAkrK1hfW3TwvrW/7YXg1/6aNV4sklc +vqn/40kCK0v9xJIv9FM/l0Nq+CMWcrb4sjLeGwHAa8ASfk6hKHbeiTFamA6FBkvQ +//7GP5khD+y62RlWi9PmwJY21lEkn2mP99THxqvZjQiAVNiqlYdwiIc7AoGBAMH8 +f2Ay7Egc2KYRYU2qwa5E/Cljn/9sdvUnWM+gOzUXpc5sBi+/SUUQT8y/rY4AUVW6 +YaK7chG9YokZQq7ZwTCsYxTfxHK2pnG/tXjOxLFQKBwppQfJcFSRLbw0lMbQoZBk +S+zb0ufZzxc2fJfXE+XeJxmKs0TS9ltQuJiSqCPPAoGBALEc84K7DBG+FGmCl1sb +ZKJVGwwknA90zCeYtadrIT0/VkxchWSPvxE5Ep+u8gxHcqrXFTdILjWW4chefOyF +5ytkTrgQAI+xawxsdyXWUZtd5dJq8lxLtx9srD4gwjh3et8ZqtFx5kCHBCu29Fr2 +PA4OmBUMfrs0tlfKgV+pT2j5AoGBAKnA0Z5XMZlxVM0OTH3wvYhI6fk2Kx8TxY2G +nxsh9m3hgcD/mvJRjEaZnZto6PFoqcRBU4taSNnpRr7+kfH8sCht0k7D+l8AIutL +ffx3xHv9zvvGHZqQ1nHKkaEuyjqo+5kli6N8QjWNzsFbdvBQ0CLJoqGhVHsXuWnz +W3Z4cBbVAoGAEtnwY1OJM7+R2u1CW0tTjqDlYU2hUNa9t1AbhyGdI2arYp+p+umA +b5VoYLNsdvZhqjVFTrYNEuhTJFYCF7jAiZLYvYm0C99BqcJnJPl7JjWynoNHNKw3 +9f6PIOE1rAmPE8Cfz/GFF5115ZKVlq+2BY8EKNxbCIy2d/vMEvisnXI= +-----END RSA PRIVATE KEY-----
@@ -0,0 +1,8 @@
+-----BEGIN RSA PUBLIC KEY----- +MIIBCgKCAQEAvzoCEC2rpSpJQaWZbUmlsDNwp83Jr4fi6KmBWIwnj1MZ6CUQ7rBa +suLI8AcfX5/10scSfQNCsTLV2tMKQaHuvyrVfwY0dINk+nkqB74QcT2oCCH9XduJ +jDuwWA4xLqAKuF96FsIes52opEM50W7/W7DZCKXkC8fFPFj6QF5ZzApDw2Qsu3yM +Rmr7/W9uWeaTwfPx24YdY7Ah+fdLy3KN40vXv9c4xiSafVvnx9BwYL7H1Q8NiK9L +GEN6+JSWfgckQCs6UUBOXSZdreNN9zbQCwyzee7bOJqXUDAuLcFARzPw1EsZAyjV +tGCKIQ0/btqK+jFunT2NBC8RItanDZpptQIDAQAB +-----END RSA PUBLIC KEY-----
@@ -0,0 +1,15 @@
+var jwt = require('../'); + +describe('public key start with BEGIN RSA PUBLIC KEY', function () { + + it('should work', function (done) { + var fs = require('fs'); + var cert_pub = fs.readFileSync(__dirname + '/rsa-public-key.pem'); + var cert_priv = fs.readFileSync(__dirname + '/rsa-private.pem'); + + var token = jwt.sign({ foo: 'bar' }, cert_priv, { algorithm: 'RS256'}); + + jwt.verify(token, cert_pub, done); + }); + +});
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvzoCEC2rpSpJQaWZbUml +sDNwp83Jr4fi6KmBWIwnj1MZ6CUQ7rBasuLI8AcfX5/10scSfQNCsTLV2tMKQaHu +vyrVfwY0dINk+nkqB74QcT2oCCH9XduJjDuwWA4xLqAKuF96FsIes52opEM50W7/ +W7DZCKXkC8fFPFj6QF5ZzApDw2Qsu3yMRmr7/W9uWeaTwfPx24YdY7Ah+fdLy3KN +40vXv9c4xiSafVvnx9BwYL7H1Q8NiK9LGEN6+JSWfgckQCs6UUBOXSZdreNN9zbQ +Cwyzee7bOJqXUDAuLcFARzPw1EsZAyjVtGCKIQ0/btqK+jFunT2NBC8RItanDZpp +tQIDAQAB +-----END PUBLIC KEY-----
@@ -0,0 +1,18 @@
+var jwt = require('../index'); +var expect = require('chai').expect; + +describe('set header', function() { + + it('should add the header', function () { + var token = jwt.sign({foo: 123}, '123', { header: { foo: 'bar' } }); + var decoded = jwt.decode(token, {complete: true}); + expect(decoded.header.foo).to.equal('bar'); + }); + + it('should allow overriding header', function () { + var token = jwt.sign({foo: 123}, '123', { header: { alg: 'HS512' } }); + var decoded = jwt.decode(token, {complete: true}); + expect(decoded.header.alg).to.equal('HS512'); + }); + +});
@@ -0,0 +1,20 @@
+var fs = require('fs'); +var jwt = require('../index'); +var JsonWebTokenError = require('../lib/JsonWebTokenError'); +var expect = require('chai').expect; + +var TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.t-IDcSemACt8x4iTMCda8Yhe3iZaWbvV5XKSTbuAn0M'; + +describe('verifying without specified secret or public key', function () { + it('should not verify null', function () { + expect(function () { + jwt.verify(TOKEN, null); + }).to.throw(JsonWebTokenError, /secret or public key must be provided/); + }); + + it('should not verify undefined', function () { + expect(function () { + jwt.verify(TOKEN); + }).to.throw(JsonWebTokenError, /secret or public key must be provided/); + }); +});
@@ -0,0 +1,32 @@
+var oldDate = global.Date; + +/* + * fix new Date() to a fixed unix timestamp. + */ +global.Date.fix = function (timestamp) { + var time = timestamp * 1000; + + if (global.Date.unfake) { + global.Date.unfake(); + } + + global.Date = function (ts) { + return new oldDate(ts || time); + }; + + global.Date.prototype = Object.create(oldDate.prototype); + global.Date.prototype.constructor = global.Date; + + global.Date.prototype.now = function () { + return time; + }; + + global.Date.now = function () { + return time; + }; + + global.Date.unfix = function () { + global.Date = oldDate; + }; + +};
@@ -0,0 +1,194 @@
+var jwt = require('../index'); +var jws = require('jws'); +var fs = require('fs'); +var path = require('path'); +var sinon = require('sinon'); + +var assert = require('chai').assert; + +describe('verify', function() { + var pub = fs.readFileSync(path.join(__dirname, 'pub.pem')); + var priv = fs.readFileSync(path.join(__dirname, 'priv.pem')); + + it('should first assume JSON claim set', function (done) { + var header = { alg: 'RS256' }; + var payload = { iat: Math.floor(Date.now() / 1000 ) }; + + var signed = jws.sign({ + header: header, + payload: payload, + secret: priv, + encoding: 'utf8' + }); + + jwt.verify(signed, pub, {typ: 'JWT'}, function(err, p) { + assert.isNull(err); + assert.deepEqual(p, payload); + done(); + }); + }); + + it('should be able to validate unsigned token', function (done) { + var header = { alg: 'none' }; + var payload = { iat: Math.floor(Date.now() / 1000 ) }; + + var signed = jws.sign({ + header: header, + payload: payload, + secret: priv, + encoding: 'utf8' + }); + + jwt.verify(signed, null, {typ: 'JWT'}, function(err, p) { + assert.isNull(err); + assert.deepEqual(p, payload); + done(); + }); + }); + + it('should not mutate options', function (done) { + var header = { alg: 'none' }; + + var payload = { iat: Math.floor(Date.now() / 1000 ) }; + + var options = {typ: 'JWT'}; + + var signed = jws.sign({ + header: header, + payload: payload, + secret: priv, + encoding: 'utf8' + }); + + jwt.verify(signed, null, options, function(err) { + assert.isNull(err); + assert.deepEqual(Object.keys(options).length, 1); + done(); + }); + }); + + describe('expiration', function () { + // { foo: 'bar', iat: 1437018582, exp: 1437018583 } + var token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE0MzcwMTg1ODIsImV4cCI6MTQzNzAxODU4M30.NmMv7sXjM1dW0eALNXud8LoXknZ0mH14GtnFclwJv0s'; + var key = 'key'; + + var clock; + afterEach(function () { + try { clock.restore(); } catch (e) {} + }); + + it('should error on expired token', function (done) { + clock = sinon.useFakeTimers(1437018650000); + var options = {algorithms: ['HS256']}; + + jwt.verify(token, key, options, function (err, p) { + assert.equal(err.name, 'TokenExpiredError'); + assert.equal(err.message, 'jwt expired'); + assert.equal(err.expiredAt.constructor.name, 'Date'); + assert.equal(Number(err.expiredAt), 1437018583000); + assert.isUndefined(p); + done(); + }); + }); + + it('should not error on expired token within clockTolerance interval', function (done) { + clock = sinon.useFakeTimers(1437018584000); + var options = {algorithms: ['HS256'], clockTolerance: 100} + + jwt.verify(token, key, options, function (err, p) { + assert.isNull(err); + assert.equal(p.foo, 'bar'); + done(); + }); + }); + + it('should not error if within maxAge timespan', function (done) { + clock = sinon.useFakeTimers(1437018582500); + var options = {algorithms: ['HS256'], maxAge: '600ms'}; + + jwt.verify(token, key, options, function (err, p) { + assert.isNull(err); + assert.equal(p.foo, 'bar'); + done(); + }); + }); + + describe('option: maxAge', function () { + it('should error for claims issued before a certain timespan', function (done) { + clock = sinon.useFakeTimers(1437018582500); + var options = {algorithms: ['HS256'], maxAge: '321ms'}; + + jwt.verify(token, key, options, function (err, p) { + assert.equal(err.name, 'TokenExpiredError'); + assert.equal(err.message, 'maxAge exceeded'); + assert.equal(err.expiredAt.constructor.name, 'Date'); + assert.equal(Number(err.expiredAt), 1437018582321); + assert.isUndefined(p); + done(); + }); + }); + + it('should not error for claims issued before a certain timespan but still inside clockTolerance timespan', function (done) { + clock = sinon.useFakeTimers(1437018582500); + var options = {algorithms: ['HS256'], maxAge: '321ms', clockTolerance: 100}; + + jwt.verify(token, key, options, function (err, p) { + assert.isNull(err); + assert.equal(p.foo, 'bar'); + done(); + }); + }); + + it('should not error if within maxAge timespan', function (done) { + clock = sinon.useFakeTimers(1437018582500); + var options = {algorithms: ['HS256'], maxAge: '600ms'}; + + jwt.verify(token, key, options, function (err, p) { + assert.isNull(err); + assert.equal(p.foo, 'bar'); + done(); + }); + }); + it('can be more restrictive than expiration', function (done) { + clock = sinon.useFakeTimers(1437018582900); + var options = {algorithms: ['HS256'], maxAge: '800ms'}; + + jwt.verify(token, key, options, function (err, p) { + assert.equal(err.name, 'TokenExpiredError'); + assert.equal(err.message, 'maxAge exceeded'); + assert.equal(err.expiredAt.constructor.name, 'Date'); + assert.equal(Number(err.expiredAt), 1437018582800); + assert.isUndefined(p); + done(); + }); + }); + it('cannot be more permissive than expiration', function (done) { + clock = sinon.useFakeTimers(1437018583100); + var options = {algorithms: ['HS256'], maxAge: '1200ms'}; + + jwt.verify(token, key, options, function (err, p) { + // maxAge not exceded, but still expired + assert.equal(err.name, 'TokenExpiredError'); + assert.equal(err.message, 'jwt expired'); + assert.equal(err.expiredAt.constructor.name, 'Date'); + assert.equal(Number(err.expiredAt), 1437018583000); + assert.isUndefined(p); + done(); + }); + }); + it('should error if maxAge is specified but there is no iat claim', function (done) { + clock = sinon.useFakeTimers(1437018582900); + var token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIifQ.0MBPd4Bru9-fK_HY3xmuDAc6N_embknmNuhdb9bKL_U'; + var options = {algorithms: ['HS256'], maxAge: '1s'}; + + jwt.verify(token, key, options, function (err, p) { + assert.equal(err.name, 'JsonWebTokenError'); + assert.equal(err.message, 'iat required when maxAge is specified'); + assert.isUndefined(p); + done(); + }); + }); + }); + }); + +});
@@ -0,0 +1,42 @@
+var fs = require('fs'); +var path = require('path'); +var jwt = require('../index'); +var JsonWebTokenError = require('../lib/JsonWebTokenError'); +var expect = require('chai').expect; + + +var pub = fs.readFileSync(path.join(__dirname, 'pub.pem'), 'utf8'); +// priv is never used +// var priv = fs.readFileSync(path.join(__dirname, 'priv.pem')); + +var TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE0MjY1NDY5MTl9.ETgkTn8BaxIX4YqvUWVFPmum3moNZ7oARZtSBXb_vP4'; + +describe('when setting a wrong `header.alg`', function () { + + describe('signing with pub key as symmetric', function () { + it('should not verify', function () { + expect(function () { + jwt.verify(TOKEN, pub); + }).to.throw(JsonWebTokenError, /invalid algorithm/); + }); + }); + + describe('signing with pub key as HS256 and whitelisting only RS256', function () { + it('should not verify', function () { + expect(function () { + jwt.verify(TOKEN, pub, {algorithms: ['RS256']}); + }).to.throw(JsonWebTokenError, /invalid algorithm/); + }); + }); + + describe('signing with HS256 and checking with HS384', function () { + it('should not verify', function () { + expect(function () { + var token = jwt.sign({foo: 'bar'}, 'secret', {algorithm: 'HS256'}); + jwt.verify(token, 'some secret', {algorithms: ['HS384']}); + }).to.throw(JsonWebTokenError, /invalid algorithm/); + }); + }); + + +});
@@ -0,0 +1,168 @@
+var JsonWebTokenError = require('./lib/JsonWebTokenError'); +var NotBeforeError = require('./lib/NotBeforeError'); +var TokenExpiredError = require('./lib/TokenExpiredError'); +var decode = require('./decode'); +var jws = require('jws'); +var ms = require('ms'); +var xtend = require('xtend'); + +module.exports = function (jwtString, secretOrPublicKey, options, callback) { + if ((typeof options === 'function') && !callback) { + callback = options; + options = {}; + } + + if (!options) { + options = {}; + } + + //clone this object since we are going to mutate it. + options = xtend(options); + var done; + + if (callback) { + done = function() { + var args = Array.prototype.slice.call(arguments, 0); + return process.nextTick(function() { + callback.apply(null, args); + }); + }; + } else { + done = function(err, data) { + if (err) throw err; + return data; + }; + } + + if (!jwtString){ + return done(new JsonWebTokenError('jwt must be provided')); + } + + var parts = jwtString.split('.'); + + if (parts.length !== 3){ + return done(new JsonWebTokenError('jwt malformed')); + } + + var hasSignature = parts[2].trim() !== ''; + + if (!hasSignature && secretOrPublicKey){ + return done(new JsonWebTokenError('jwt signature is required')); + } + + if (hasSignature && !secretOrPublicKey) { + return done(new JsonWebTokenError('secret or public key must be provided')); + } + + if (!hasSignature && !options.algorithms) { + options.algorithms = ['none']; + } + + if (!options.algorithms) { + options.algorithms = ~secretOrPublicKey.toString().indexOf('BEGIN CERTIFICATE') || + ~secretOrPublicKey.toString().indexOf('BEGIN PUBLIC KEY') ? + [ 'RS256','RS384','RS512','ES256','ES384','ES512' ] : + ~secretOrPublicKey.toString().indexOf('BEGIN RSA PUBLIC KEY') ? + [ 'RS256','RS384','RS512' ] : + [ 'HS256','HS384','HS512' ]; + + } + + var decodedToken; + try { + decodedToken = jws.decode(jwtString); + } catch(err) { + return done(new JsonWebTokenError('invalid token')); + } + + if (!decodedToken) { + return done(new JsonWebTokenError('invalid token')); + } + + var header = decodedToken.header; + + if (!~options.algorithms.indexOf(header.alg)) { + return done(new JsonWebTokenError('invalid algorithm')); + } + + var valid; + + try { + valid = jws.verify(jwtString, header.alg, secretOrPublicKey); + } catch (e) { + return done(e); + } + + if (!valid) + return done(new JsonWebTokenError('invalid signature')); + + var payload; + + try { + payload = decode(jwtString); + } catch(err) { + return done(err); + } + + if (typeof payload.nbf !== 'undefined' && !options.ignoreNotBefore) { + if (typeof payload.nbf !== 'number') { + return done(new JsonWebTokenError('invalid nbf value')); + } + if (payload.nbf > Math.floor(Date.now() / 1000) + (options.clockTolerance || 0)) { + return done(new NotBeforeError('jwt not active', new Date(payload.nbf * 1000))); + } + } + + if (typeof payload.exp !== 'undefined' && !options.ignoreExpiration) { + if (typeof payload.exp !== 'number') { + return done(new JsonWebTokenError('invalid exp value')); + } + if (Math.floor(Date.now() / 1000) >= payload.exp + (options.clockTolerance || 0)) { + return done(new TokenExpiredError('jwt expired', new Date(payload.exp * 1000))); + } + } + + if (options.audience) { + var audiences = Array.isArray(options.audience)? options.audience : [options.audience]; + var target = Array.isArray(payload.aud) ? payload.aud : [payload.aud]; + + var match = target.some(function(aud) { return audiences.indexOf(aud) != -1; }); + + if (!match) + return done(new JsonWebTokenError('jwt audience invalid. expected: ' + audiences.join(' or '))); + } + + if (options.issuer) { + var invalid_issuer = + (typeof options.issuer === 'string' && payload.iss !== options.issuer) || + (Array.isArray(options.issuer) && options.issuer.indexOf(payload.iss) === -1); + + if (invalid_issuer) { + return done(new JsonWebTokenError('jwt issuer invalid. expected: ' + options.issuer)); + } + } + + if (options.subject) { + if (payload.sub !== options.subject) { + return done(new JsonWebTokenError('jwt subject invalid. expected: ' + options.subject)); + } + } + + if (options.jwtid) { + if (payload.jti !== options.jwtid) { + return done(new JsonWebTokenError('jwt jwtid invalid. expected: ' + options.jwtid)); + } + } + + if (options.maxAge) { + var maxAge = ms(options.maxAge); + if (typeof payload.iat !== 'number') { + return done(new JsonWebTokenError('iat required when maxAge is specified')); + } + if (Date.now() - (payload.iat * 1000) > maxAge + (options.clockTolerance || 0) * 1000) { + return done(new TokenExpiredError('maxAge exceeded', new Date(payload.iat * 1000 + maxAge))); + } + } + + return done(null, payload); +};
@@ -66,5 +66,7 @@ "email": "christkv@gmail.com"
} ], "_shasum": "3dbf984acb9d33a6878b46e6fb7afbd611856a60", - "_resolved": "https://registry.npmjs.org/bson/-/bson-0.2.2.tgz" + "_resolved": "https://registry.npmjs.org/bson/-/bson-0.2.2.tgz", + "readme": "ERROR: No README data found!", + "homepage": "https://github.com/mongodb/js-bson#readme" }
@@ -172,7 +172,7 @@ }
], "repository": { "type": "git", - "url": "http://github.com/mongodb/node-mongodb-native.git" + "url": "git+ssh://git@github.com/mongodb/node-mongodb-native.git" }, "bugs": { "url": "http://github.com/mongodb/node-mongodb-native/issues"@@ -235,5 +235,6 @@ "email": "christkv@gmail.com"
} ], "_shasum": "f229db24098f019d86d135aaf8a1ab5f2658b1d4", - "_resolved": "https://registry.npmjs.org/mongodb/-/mongodb-1.3.19.tgz" + "_resolved": "https://registry.npmjs.org/mongodb/-/mongodb-1.3.19.tgz", + "readme": "ERROR: No README data found!" }
@@ -0,0 +1,158 @@
+1.7.0 / 2016-02-18 +================== + + * Add `digits` argument to `response-time` token + * deps: depd@~1.1.0 + - Enable strict mode in more places + - Support web browser loading + * deps: on-headers@~1.0.1 + - perf: enable strict mode + +1.6.1 / 2015-07-03 +================== + + * deps: basic-auth@~1.0.3 + +1.6.0 / 2015-06-12 +================== + + * Add `morgan.compile(format)` export + * Do not color 1xx status codes in `dev` format + * Fix `response-time` token to not include response latency + * Fix `status` token incorrectly displaying before response in `dev` format + * Fix token return values to be `undefined` or a string + * Improve representation of multiple headers in `req` and `res` tokens + * Use `res.getHeader` in `res` token + * deps: basic-auth@~1.0.2 + - perf: enable strict mode + - perf: hoist regular expression + - perf: parse with regular expressions + - perf: remove argument reassignment + * deps: on-finished@~2.3.0 + - Add defined behavior for HTTP `CONNECT` requests + - Add defined behavior for HTTP `Upgrade` requests + - deps: ee-first@1.1.1 + * pref: enable strict mode + * pref: reduce function closure scopes + * pref: remove dynamic compile on every request for `dev` format + * pref: remove an argument reassignment + * pref: skip function call without `skip` option + +1.5.3 / 2015-05-10 +================== + + * deps: basic-auth@~1.0.1 + * deps: debug@~2.2.0 + - deps: ms@0.7.1 + * deps: depd@~1.0.1 + * deps: on-finished@~2.2.1 + - Fix `isFinished(req)` when data buffered + +1.5.2 / 2015-03-15 +================== + + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + +1.5.1 / 2014-12-31 +================== + + * deps: debug@~2.1.1 + * deps: on-finished@~2.2.0 + +1.5.0 / 2014-11-06 +================== + + * Add multiple date formats + - `clf` for the common log format + - `iso` for the common ISO 8601 date time format + - `web` for the common RFC 1123 date time format + * Deprecate `buffer` option + * Fix date format in `common` and `combined` formats + * Fix token arguments to accept values with `"` + +1.4.1 / 2014-10-22 +================== + + * deps: on-finished@~2.1.1 + - Fix handling of pipelined requests + +1.4.0 / 2014-10-16 +================== + + * Add `debug` messages + * deps: depd@~1.0.0 + +1.3.2 / 2014-09-27 +================== + + * Fix `req.ip` integration when `immediate: false` + +1.3.1 / 2014-09-14 +================== + + * Remove un-used `bytes` dependency + * deps: depd@0.4.5 + +1.3.0 / 2014-09-01 +================== + + * Assert if `format` is not a function or string + +1.2.3 / 2014-08-16 +================== + + * deps: on-finished@2.1.0 + +1.2.2 / 2014-07-27 +================== + + * deps: depd@0.4.4 + - Work-around v8 generating empty stack traces + +1.2.1 / 2014-07-26 +================== + + * deps: depd@0.4.3 + - Fix exception when global `Error.stackTraceLimit` is too low + +1.2.0 / 2014-07-19 +================== + + * Add `:remote-user` token + * Add `combined` log format + * Add `common` log format + * Add `morgan(format, options)` function signature + * Deprecate `default` format -- use `combined` format instead + * Deprecate not providing a format + * Remove non-standard grey color from `dev` format + +1.1.1 / 2014-05-20 +================== + + * simplify method to get remote address + +1.1.0 / 2014-05-18 +================== + + * "dev" format will use same tokens as other formats + * `:response-time` token is now empty when immediate used + * `:response-time` token is now monotonic + * `:response-time` token has precision to 1 μs + * fix `:status` + immediate output in node.js 0.8 + * improve `buffer` option to prevent indefinite event loop holding + * deps: bytes@1.0.0 + - add negative support + +1.0.1 / 2014-05-04 +================== + + * Make buffer unique per morgan instance + * deps: bytes@0.3.0 + * added terabyte support + +1.0.0 / 2014-02-08 +================== + + * Initial release
@@ -0,0 +1,23 @@
+(The MIT License) + +Copyright (c) 2014 Jonathan Ong <me@jongleberry.com> +Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,324 @@
+# morgan + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] +[![Gratipay][gratipay-image]][gratipay-url] + +HTTP request logger middleware for node.js + +> Named after [Dexter](http://en.wikipedia.org/wiki/Dexter_Morgan), a show you should not watch until completion. + +## API + +```js +var morgan = require('morgan') +``` + +### morgan(format, options) + +Create a new morgan logger middleware function using the given `format` and `options`. +The `format` argument may be a string of a predefined name (see below for the names), +a string of a format string, or a function that will produce a log entry. + +#### Options + +Morgan accepts these properties in the options object. + +#### immediate + +Write log line on request instead of response. This means that a requests will +be logged even if the server crashes, _but data from the response (like the +response code, content length, etc.) cannot be logged_. + +##### skip + +Function to determine if logging is skipped, defaults to `false`. This function +will be called as `skip(req, res)`. + +```js +// EXAMPLE: only log error responses +morgan('combined', { + skip: function (req, res) { return res.statusCode < 400 } +}) +``` + +##### stream + +Output stream for writing log lines, defaults to `process.stdout`. + +#### Predefined Formats + +There are various pre-defined formats provided: + +##### combined + +Standard Apache combined log output. + +``` +:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent" +``` + +##### common + +Standard Apache common log output. + +``` +:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] +``` + +##### dev + +Concise output colored by response status for development use. The `:status` +token will be colored red for server error codes, yellow for client error +codes, cyan for redirection codes, and uncolored for all other codes. + +``` +:method :url :status :response-time ms - :res[content-length] +``` + +##### short + +Shorter than default, also including response time. + +``` +:remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms +``` + +##### tiny + +The minimal output. + +``` +:method :url :status :res[content-length] - :response-time ms +``` + +#### Tokens + +##### Creating new tokens + +To define a token, simply invoke `morgan.token()` with the name and a callback function. This callback function is expected to return a string value. The value returned is then available as ":type" in this case: +```js +morgan.token('type', function(req, res){ return req.headers['content-type']; }) +``` + +Calling `morgan.token()` using the same name as an existing token will overwrite that token definition. + +##### :date[format] + +The current date and time in UTC. The available formats are: + + - `clf` for the common log format (`"10/Oct/2000:13:55:36 +0000"`) + - `iso` for the common ISO 8601 date time format (`2000-10-10T13:55:36.000Z`) + - `web` for the common RFC 1123 date time format (`Tue, 10 Oct 2000 13:55:36 GMT`) + +If no format is given, then the default is `web`. + +##### :http-version + +The HTTP version of the request. + +##### :method + +The HTTP method of the request. + +##### :referrer + +The Referrer header of the request. This will use the standard mis-spelled Referer header if exists, otherwise Referrer. + +##### :remote-addr + +The remote address of the request. This will use `req.ip`, otherwise the standard `req.connection.remoteAddress` value (socket address). + +##### :remote-user + +The user authenticated as part of Basic auth for the request. + +##### :req[header] + +The given `header` of the request. + +##### :res[header] + +The given `header` of the response. + +##### :response-time[digits] + +The time between the request coming into `morgan` and when the response +headers are written, in milliseconds. + +The `digits` argument is a number that specifies the number of digits to +include on the number, defaulting to `3`, which provides microsecond percision. + +##### :status + +The status code of the response. + +If the request/response cycle completes before a response was sent to the +client (for example, the TCP socket closed prematurely by a client aborting +the request), then the status will be empty (displayed as `"-"` in the log). + +##### :url + +The URL of the request. This will use `req.originalUrl` if exists, otherwise `req.url`. + +##### :user-agent + +The contents of the User-Agent header of the request. + +### morgan.compile(format) + +Compile a format string into a function for use by `morgan`. A format string +is a string that represents a single log line and can utilize token syntax. +Tokens are references by `:token-name`. If tokens accept arguments, they can +be passed using `[]`, for example: `:token-name[pretty]` would pass the string +`'pretty'` as an argument to the token `token-name`. + +Normally formats are defined using `morgan.format(name, format)`, but for certain +advanced uses, this compile function is directly available. + +## Examples + +### express/connect + +Simple app that will log all request in the Apache combined format to STDOUT + +```js +var express = require('express') +var morgan = require('morgan') + +var app = express() + +app.use(morgan('combined')) + +app.get('/', function (req, res) { + res.send('hello, world!') +}) +``` + +### vanilla http server + +Simple app that will log all request in the Apache combined format to STDOUT + +```js +var finalhandler = require('finalhandler') +var http = require('http') +var morgan = require('morgan') + +// create "middleware" +var logger = morgan('combined') + +http.createServer(function (req, res) { + var done = finalhandler(req, res) + logger(req, res, function (err) { + if (err) return done(err) + + // respond to request + res.setHeader('content-type', 'text/plain') + res.end('hello, world!') + }) +}) +``` + +### write logs to a file + +#### single file + +Simple app that will log all requests in the Apache combined format to the file +`access.log`. + +```js +var express = require('express') +var fs = require('fs') +var morgan = require('morgan') + +var app = express() + +// create a write stream (in append mode) +var accessLogStream = fs.createWriteStream(__dirname + '/access.log', {flags: 'a'}) + +// setup the logger +app.use(morgan('combined', {stream: accessLogStream})) + +app.get('/', function (req, res) { + res.send('hello, world!') +}) +``` + +#### log file rotation + +Simple app that will log all requests in the Apache combined format to one log +file per date in the `log/` directory using the +[file-stream-rotator module](https://www.npmjs.com/package/file-stream-rotator). + +```js +var FileStreamRotator = require('file-stream-rotator') +var express = require('express') +var fs = require('fs') +var morgan = require('morgan') + +var app = express() +var logDirectory = __dirname + '/log' + +// ensure log directory exists +fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory) + +// create a rotating write stream +var accessLogStream = FileStreamRotator.getStream({ + date_format: 'YYYYMMDD', + filename: logDirectory + '/access-%DATE%.log', + frequency: 'daily', + verbose: false +}) + +// setup the logger +app.use(morgan('combined', {stream: accessLogStream})) + +app.get('/', function (req, res) { + res.send('hello, world!') +}) +``` + +### use custom token formats + +Sample app that will use custom token formats. This adds an ID to all requests and displays it using the `:id` token. + +```js +var express = require('express') +var morgan = require('morgan') +var uuid = require('node-uuid') + +morgan.token('id', function getId(req) { + return req.id +}) + +var app = express() + +app.use(assignId) +app.use(morgan(':id :method :url :response-time')) + +app.get('/', function (req, res) { + res.send('hello, world!') +}) + +function assignId(req, res, next) { + req.id = uuid.v4() + next() +} +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/morgan.svg +[npm-url]: https://npmjs.org/package/morgan +[travis-image]: https://img.shields.io/travis/expressjs/morgan/master.svg +[travis-url]: https://travis-ci.org/expressjs/morgan +[coveralls-image]: https://img.shields.io/coveralls/expressjs/morgan/master.svg +[coveralls-url]: https://coveralls.io/r/expressjs/morgan?branch=master +[downloads-image]: https://img.shields.io/npm/dm/morgan.svg +[downloads-url]: https://npmjs.org/package/morgan +[gratipay-image]: https://img.shields.io/gratipay/dougwilson.svg +[gratipay-url]: https://www.gratipay.com/dougwilson/
@@ -0,0 +1,501 @@
+/*! + * morgan + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = morgan +module.exports.compile = compile +module.exports.format = format +module.exports.token = token + +/** + * Module dependencies. + * @private + */ + +var auth = require('basic-auth') +var debug = require('debug')('morgan') +var deprecate = require('depd')('morgan') +var onFinished = require('on-finished') +var onHeaders = require('on-headers') + +/** + * Array of CLF month names. + * @private + */ + +var clfmonth = [ + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' +] + +/** + * Default log buffer duration. + * @private + */ + +var defaultBufferDuration = 1000; + +/** + * Create a logger middleware. + * + * @public + * @param {String|Function} format + * @param {Object} [options] + * @return {Function} middleware + */ + +function morgan(format, options) { + var fmt = format + var opts = options || {} + + if (format && typeof format === 'object') { + opts = format + fmt = opts.format || 'default' + + // smart deprecation message + deprecate('morgan(options): use morgan(' + (typeof fmt === 'string' ? JSON.stringify(fmt) : 'format') + ', options) instead') + } + + if (fmt === undefined) { + deprecate('undefined format: specify a format') + } + + // output on request instead of response + var immediate = opts.immediate + + // check if log entry should be skipped + var skip = opts.skip || false + + // format function + var formatLine = typeof fmt !== 'function' + ? getFormatFunction(fmt) + : fmt + + // stream + var buffer = opts.buffer + var stream = opts.stream || process.stdout + + // buffering support + if (buffer) { + deprecate('buffer option') + + // flush interval + var interval = typeof buffer !== 'number' + ? defaultBufferDuration + : buffer + + // swap the stream + stream = createBufferStream(stream, interval) + } + + return function logger(req, res, next) { + // request data + req._startAt = undefined + req._startTime = undefined + req._remoteAddress = getip(req) + + // response data + res._startAt = undefined + res._startTime = undefined + + // record request start + recordStartTime.call(req) + + function logRequest() { + if (skip !== false && skip(req, res)) { + debug('skip request') + return + } + + var line = formatLine(morgan, req, res) + + if (null == line) { + debug('skip line') + return + } + + debug('log request') + stream.write(line + '\n') + }; + + if (immediate) { + // immediate log + logRequest() + } else { + // record response start + onHeaders(res, recordStartTime) + + // log when response finished + onFinished(res, logRequest) + } + + next(); + }; +} + +/** + * Apache combined log format. + */ + +morgan.format('combined', ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"') + +/** + * Apache common log format. + */ + +morgan.format('common', ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]') + +/** + * Default format. + */ + +morgan.format('default', ':remote-addr - :remote-user [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"') +deprecate.property(morgan, 'default', 'default format: use combined format') + +/** + * Short format. + */ + +morgan.format('short', ':remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms') + +/** + * Tiny format. + */ + +morgan.format('tiny', ':method :url :status :res[content-length] - :response-time ms') + +/** + * dev (colored) + */ + +morgan.format('dev', function developmentFormatLine(tokens, req, res) { + // get the status code if response written + var status = res._header + ? res.statusCode + : undefined + + // get status color + var color = status >= 500 ? 31 // red + : status >= 400 ? 33 // yellow + : status >= 300 ? 36 // cyan + : status >= 200 ? 32 // green + : 0 // no color + + // get colored function + var fn = developmentFormatLine[color] + + if (!fn) { + // compile + fn = developmentFormatLine[color] = compile('\x1b[0m:method :url \x1b[' + + color + 'm:status \x1b[0m:response-time ms - :res[content-length]\x1b[0m') + } + + return fn(tokens, req, res) +}) + +/** + * request url + */ + +morgan.token('url', function getUrlToken(req) { + return req.originalUrl || req.url +}) + +/** + * request method + */ + +morgan.token('method', function getMethodToken(req) { + return req.method; +}); + +/** + * response time in milliseconds + */ + +morgan.token('response-time', function getResponseTimeToken(req, res, digits) { + if (!req._startAt || !res._startAt) { + // missing request and/or response start time + return + } + + // calculate diff + var ms = (res._startAt[0] - req._startAt[0]) * 1e3 + + (res._startAt[1] - req._startAt[1]) * 1e-6 + + // return truncated value + return ms.toFixed(digits === undefined ? 3 : digits) +}) + +/** + * current date + */ + +morgan.token('date', function getDateToken(req, res, format) { + var date = new Date() + + switch (format || 'web') { + case 'clf': + return clfdate(date) + case 'iso': + return date.toISOString() + case 'web': + return date.toUTCString() + } +}); + +/** + * response status code + */ + +morgan.token('status', function getStatusToken(req, res) { + return res._header + ? String(res.statusCode) + : undefined +}) + +/** + * normalized referrer + */ + +morgan.token('referrer', function getReferrerToken(req) { + return req.headers['referer'] || req.headers['referrer']; +}); + +/** + * remote address + */ + +morgan.token('remote-addr', getip) + +/** + * remote user + */ + +morgan.token('remote-user', function getRemoteUserToken(req) { + // parse basic credentials + var credentials = auth(req) + + // return username + return credentials + ? credentials.name + : undefined +}) + +/** + * HTTP version + */ + +morgan.token('http-version', function getHttpVersionToken(req) { + return req.httpVersionMajor + '.' + req.httpVersionMinor +}) + +/** + * UA string + */ + +morgan.token('user-agent', function getUserAgentToken(req) { + return req.headers['user-agent']; +}); + +/** + * request header + */ + +morgan.token('req', function getRequestToken(req, res, field) { + // get header + var header = req.headers[field.toLowerCase()] + + return Array.isArray(header) + ? header.join(', ') + : header +}) + +/** + * response header + */ + +morgan.token('res', function getResponseTime(req, res, field) { + if (!res._header) { + return undefined + } + + // get header + var header = res.getHeader(field) + + return Array.isArray(header) + ? header.join(', ') + : header +}) + +/** + * Format a Date in the common log format. + * + * @private + * @param {Date} dateTime + * @return {string} + */ + +function clfdate(dateTime) { + var date = dateTime.getUTCDate() + var hour = dateTime.getUTCHours() + var mins = dateTime.getUTCMinutes() + var secs = dateTime.getUTCSeconds() + var year = dateTime.getUTCFullYear() + + var month = clfmonth[dateTime.getUTCMonth()] + + return pad2(date) + '/' + month + '/' + year + + ':' + pad2(hour) + ':' + pad2(mins) + ':' + pad2(secs) + + ' +0000' +} + +/** + * Compile a format string into a function. + * + * @param {string} format + * @return {function} + * @public + */ + +function compile(format) { + if (typeof format !== 'string') { + throw new TypeError('argument format must be a string') + } + + var fmt = format.replace(/"/g, '\\"') + var js = ' return "' + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function(_, name, arg) { + return '"\n + (tokens["' + name + '"](req, res, ' + String(JSON.stringify(arg)) + ') || "-") + "' + }) + '";' + + return new Function('tokens, req, res', js) +} + +/** + * Create a basic buffering stream. + * + * @param {object} stream + * @param {number} interval + * @public + */ + +function createBufferStream(stream, interval) { + var buf = [] + var timer = null + + // flush function + function flush() { + timer = null + stream.write(buf.join('')) + buf.length = 0 + } + + // write function + function write(str) { + if (timer === null) { + timer = setTimeout(flush, interval) + } + + buf.push(str) + } + + // return a minimal "stream" + return { write: write } +} + +/** + * Define a format with the given name. + * + * @param {string} name + * @param {string|function} fmt + * @public + */ + +function format(name, fmt) { + morgan[name] = fmt + return this +} + +/** + * Lookup and compile a named format function. + * + * @param {string} name + * @return {function} + * @public + */ + +function getFormatFunction(name) { + // lookup format + var fmt = morgan[name] || name || morgan.default + + // return compiled format + return typeof fmt !== 'function' + ? compile(fmt) + : fmt +} + +/** + * Get request IP address. + * + * @private + * @param {IncomingMessage} req + * @return {string} + */ + +function getip(req) { + return req.ip + || req._remoteAddress + || (req.connection && req.connection.remoteAddress) + || undefined; +} + +/** + * Pad number to two digits. + * + * @private + * @param {number} num + * @return {string} + */ + +function pad2(num) { + var str = String(num) + + return (str.length === 1 ? '0' : '') + + str +} + +/** + * Record the start time. + * @private + */ + +function recordStartTime() { + this._startAt = process.hrtime() + this._startTime = new Date() +} + +/** + * Define a token function with the given name, + * and callback fn(req, res). + * + * @param {string} name + * @param {function} fn + * @public + */ + +function token(name, fn) { + morgan[name] = fn + return this +}
@@ -0,0 +1,35 @@
+1.0.4 / 2016-05-10 +================== + + * Improve error message when `req` argument is not an object + * Improve error message when `req` missing `headers` property + +1.0.3 / 2015-07-01 +================== + + * Fix regression accepting a Koa context + +1.0.2 / 2015-06-12 +================== + + * Improve error message when `req` argument missing + * perf: enable strict mode + * perf: hoist regular expression + * perf: parse with regular expressions + * perf: remove argument reassignment + +1.0.1 / 2015-05-04 +================== + + * Update readme + +1.0.0 / 2014-07-01 +================== + + * Support empty password + * Support empty username + +0.0.1 / 2013-11-30 +================== + + * Initial release
@@ -0,0 +1,24 @@
+(The MIT License) + +Copyright (c) 2013 TJ Holowaychuk +Copyright (c) 2014 Jonathan Ong <me@jongleberry.com> +Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,78 @@
+# basic-auth + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Generic basic auth Authorization header field parser for whatever. + +## Installation + +``` +$ npm install basic-auth +``` + +## API + +```js +var auth = require('basic-auth') +``` + +### auth(req) + +Get the basic auth credentials from the given request. The `Authorization` +header is parsed and if the header is invalid, `undefined` is returned, +otherwise an object with `name` and `pass` properties. + +## Example + +Pass a node request or koa Context object to the module exported. If +parsing fails `undefined` is returned, otherwise an object with +`.name` and `.pass`. + +```js +var auth = require('basic-auth'); +var user = auth(req); +// => { name: 'something', pass: 'whatever' } + +``` + +### With vanilla node.js http server + +```js +var http = require('http') +var auth = require('basic-auth') + +// Create server +var server = http.createServer(function (req, res) { + var credentials = auth(req) + + if (!credentials || credentials.name !== 'john' || credentials.pass !== 'secret') { + res.statusCode = 401 + res.setHeader('WWW-Authenticate', 'Basic realm="example"') + res.end('Access denied') + } else { + res.end('Access granted') + } +}) + +// Listen +server.listen(3000) +``` + +# License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/basic-auth.svg +[npm-url]: https://npmjs.org/package/basic-auth +[node-version-image]: https://img.shields.io/node/v/basic-auth.svg +[node-version-url]: https://nodejs.org/en/download +[travis-image]: https://img.shields.io/travis/jshttp/basic-auth/master.svg +[travis-url]: https://travis-ci.org/jshttp/basic-auth +[coveralls-image]: https://img.shields.io/coveralls/jshttp/basic-auth/master.svg +[coveralls-url]: https://coveralls.io/r/jshttp/basic-auth?branch=master +[downloads-image]: https://img.shields.io/npm/dm/basic-auth.svg +[downloads-url]: https://npmjs.org/package/basic-auth
@@ -0,0 +1,108 @@
+/*! + * basic-auth + * Copyright(c) 2013 TJ Holowaychuk + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = auth + +/** + * RegExp for basic auth credentials + * + * credentials = auth-scheme 1*SP token68 + * auth-scheme = "Basic" ; case insensitive + * token68 = 1*( ALPHA / DIGIT / "-" / "." / "_" / "~" / "+" / "/" ) *"=" + * @private + */ + +var credentialsRegExp = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9\-\._~\+\/]+=*) *$/ + +/** + * RegExp for basic auth user/pass + * + * user-pass = userid ":" password + * userid = *<TEXT excluding ":"> + * password = *TEXT + * @private + */ + +var userPassRegExp = /^([^:]*):(.*)$/ + +/** + * Parse the Authorization header field of a request. + * + * @param {object} req + * @return {object} with .name and .pass + * @public + */ + +function auth(req) { + if (!req) { + throw new TypeError('argument req is required') + } + + if (typeof req !== 'object') { + throw new TypeError('argument req is required to be an object') + } + + // get header + var header = getAuthorization(req.req || req) + + // parse header + var match = credentialsRegExp.exec(header || '') + + if (!match) { + return + } + + // decode user pass + var userPass = userPassRegExp.exec(decodeBase64(match[1])) + + if (!userPass) { + return + } + + // return credentials object + return new Credentials(userPass[1], userPass[2]) +} + +/** + * Decode base64 string. + * @private + */ + +function decodeBase64(str) { + return new Buffer(str, 'base64').toString() +} + +/** + * Get the Authorization header from request object. + * @private + */ + +function getAuthorization(req) { + if (!req.headers || typeof req.headers !== 'object') { + throw new TypeError('argument req is required to have headers property') + } + + return req.headers.authorization +} + +/** + * Object to represent user credentials. + * @private + */ + +function Credentials(name, pass) { + this.name = name + this.pass = pass +}
@@ -0,0 +1,75 @@
+{ + "name": "basic-auth", + "description": "node.js basic auth parser", + "version": "1.0.4", + "license": "MIT", + "keywords": [ + "basic", + "auth", + "authorization", + "basicauth" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/basic-auth.git" + }, + "devDependencies": { + "istanbul": "0.4.3", + "mocha": "1.21.5" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "index.js" + ], + "engines": { + "node": ">= 0.6" + }, + "scripts": { + "test": "mocha --check-leaks --reporter spec --bail", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "gitHead": "4682d99600383bad5a266efbaa5055657dd9891d", + "bugs": { + "url": "https://github.com/jshttp/basic-auth/issues" + }, + "homepage": "https://github.com/jshttp/basic-auth#readme", + "_id": "basic-auth@1.0.4", + "_shasum": "030935b01de7c9b94a824b29f3fccb750d3a5290", + "_from": "basic-auth@>=1.0.3 <1.1.0", + "_npmVersion": "2.15.1", + "_nodeVersion": "4.4.3", + "_npmUser": { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + "dist": { + "shasum": "030935b01de7c9b94a824b29f3fccb750d3a5290", + "tarball": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz" + }, + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "jonathanong", + "email": "jonathanrichardong@gmail.com" + }, + { + "name": "jongleberry", + "email": "jonathanrichardong@gmail.com" + }, + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + } + ], + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/basic-auth-1.0.4.tgz_1462938878912_0.717464140150696" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz" +}
@@ -0,0 +1,6 @@
+support +test +examples +example +*.sock +dist
@@ -0,0 +1,195 @@
+ +2.2.0 / 2015-05-09 +================== + + * package: update "ms" to v0.7.1 (#202, @dougwilson) + * README: add logging to file example (#193, @DanielOchoa) + * README: fixed a typo (#191, @amir-s) + * browser: expose `storage` (#190, @stephenmathieson) + * Makefile: add a `distclean` target (#189, @stephenmathieson) + +2.1.3 / 2015-03-13 +================== + + * Updated stdout/stderr example (#186) + * Updated example/stdout.js to match debug current behaviour + * Renamed example/stderr.js to stdout.js + * Update Readme.md (#184) + * replace high intensity foreground color for bold (#182, #183) + +2.1.2 / 2015-03-01 +================== + + * dist: recompile + * update "ms" to v0.7.0 + * package: update "browserify" to v9.0.3 + * component: fix "ms.js" repo location + * changed bower package name + * updated documentation about using debug in a browser + * fix: security error on safari (#167, #168, @yields) + +2.1.1 / 2014-12-29 +================== + + * browser: use `typeof` to check for `console` existence + * browser: check for `console.log` truthiness (fix IE 8/9) + * browser: add support for Chrome apps + * Readme: added Windows usage remarks + * Add `bower.json` to properly support bower install + +2.1.0 / 2014-10-15 +================== + + * node: implement `DEBUG_FD` env variable support + * package: update "browserify" to v6.1.0 + * package: add "license" field to package.json (#135, @panuhorsmalahti) + +2.0.0 / 2014-09-01 +================== + + * package: update "browserify" to v5.11.0 + * node: use stderr rather than stdout for logging (#29, @stephenmathieson) + +1.0.4 / 2014-07-15 +================== + + * dist: recompile + * example: remove `console.info()` log usage + * example: add "Content-Type" UTF-8 header to browser example + * browser: place %c marker after the space character + * browser: reset the "content" color via `color: inherit` + * browser: add colors support for Firefox >= v31 + * debug: prefer an instance `log()` function over the global one (#119) + * Readme: update documentation about styled console logs for FF v31 (#116, @wryk) + +1.0.3 / 2014-07-09 +================== + + * Add support for multiple wildcards in namespaces (#122, @seegno) + * browser: fix lint + +1.0.2 / 2014-06-10 +================== + + * browser: update color palette (#113, @gscottolson) + * common: make console logging function configurable (#108, @timoxley) + * node: fix %o colors on old node <= 0.8.x + * Makefile: find node path using shell/which (#109, @timoxley) + +1.0.1 / 2014-06-06 +================== + + * browser: use `removeItem()` to clear localStorage + * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777) + * package: add "contributors" section + * node: fix comment typo + * README: list authors + +1.0.0 / 2014-06-04 +================== + + * make ms diff be global, not be scope + * debug: ignore empty strings in enable() + * node: make DEBUG_COLORS able to disable coloring + * *: export the `colors` array + * npmignore: don't publish the `dist` dir + * Makefile: refactor to use browserify + * package: add "browserify" as a dev dependency + * Readme: add Web Inspector Colors section + * node: reset terminal color for the debug content + * node: map "%o" to `util.inspect()` + * browser: map "%j" to `JSON.stringify()` + * debug: add custom "formatters" + * debug: use "ms" module for humanizing the diff + * Readme: add "bash" syntax highlighting + * browser: add Firebug color support + * browser: add colors for WebKit browsers + * node: apply log to `console` + * rewrite: abstract common logic for Node & browsers + * add .jshintrc file + +0.8.1 / 2014-04-14 +================== + + * package: re-add the "component" section + +0.8.0 / 2014-03-30 +================== + + * add `enable()` method for nodejs. Closes #27 + * change from stderr to stdout + * remove unnecessary index.js file + +0.7.4 / 2013-11-13 +================== + + * remove "browserify" key from package.json (fixes something in browserify) + +0.7.3 / 2013-10-30 +================== + + * fix: catch localStorage security error when cookies are blocked (Chrome) + * add debug(err) support. Closes #46 + * add .browser prop to package.json. Closes #42 + +0.7.2 / 2013-02-06 +================== + + * fix package.json + * fix: Mobile Safari (private mode) is broken with debug + * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript + +0.7.1 / 2013-02-05 +================== + + * add repository URL to package.json + * add DEBUG_COLORED to force colored output + * add browserify support + * fix component. Closes #24 + +0.7.0 / 2012-05-04 +================== + + * Added .component to package.json + * Added debug.component.js build + +0.6.0 / 2012-03-16 +================== + + * Added support for "-" prefix in DEBUG [Vinay Pulim] + * Added `.enabled` flag to the node version [TooTallNate] + +0.5.0 / 2012-02-02 +================== + + * Added: humanize diffs. Closes #8 + * Added `debug.disable()` to the CS variant + * Removed padding. Closes #10 + * Fixed: persist client-side variant again. Closes #9 + +0.4.0 / 2012-02-01 +================== + + * Added browser variant support for older browsers [TooTallNate] + * Added `debug.enable('project:*')` to browser variant [TooTallNate] + * Added padding to diff (moved it to the right) + +0.3.0 / 2012-01-26 +================== + + * Added millisecond diff when isatty, otherwise UTC string + +0.2.0 / 2012-01-22 +================== + + * Added wildcard support + +0.1.0 / 2011-12-02 +================== + + * Added: remove colors unless stderr isatty [TooTallNate] + +0.0.1 / 2010-01-03 +================== + + * Initial release
@@ -0,0 +1,36 @@
+ +# get Makefile directory name: http://stackoverflow.com/a/5982798/376773 +THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) +THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd) + +# BIN directory +BIN := $(THIS_DIR)/node_modules/.bin + +# applications +NODE ?= $(shell which node) +NPM ?= $(NODE) $(shell which npm) +BROWSERIFY ?= $(NODE) $(BIN)/browserify + +all: dist/debug.js + +install: node_modules + +clean: + @rm -rf dist + +dist: + @mkdir -p $@ + +dist/debug.js: node_modules browser.js debug.js dist + @$(BROWSERIFY) \ + --standalone debug \ + . > $@ + +distclean: clean + @rm -rf node_modules + +node_modules: package.json + @NODE_ENV= $(NPM) install + @touch node_modules + +.PHONY: all install clean distclean
@@ -0,0 +1,188 @@
+# debug + + tiny node.js debugging utility modelled after node core's debugging technique. + +## Installation + +```bash +$ npm install debug +``` + +## Usage + + With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility. + +Example _app.js_: + +```js +var debug = require('debug')('http') + , http = require('http') + , name = 'My App'; + +// fake app + +debug('booting %s', name); + +http.createServer(function(req, res){ + debug(req.method + ' ' + req.url); + res.end('hello\n'); +}).listen(3000, function(){ + debug('listening'); +}); + +// fake worker of some kind + +require('./worker'); +``` + +Example _worker.js_: + +```js +var debug = require('debug')('worker'); + +setInterval(function(){ + debug('doing some work'); +}, 1000); +``` + + The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples: + +  + +  + +#### Windows note + + On Windows the environment variable is set using the `set` command. + + ```cmd + set DEBUG=*,-not_this + ``` + +Then, run the program to be debugged as usual. + +## Millisecond diff + + When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls. + +  + + When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below: + +  + +## Conventions + + If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". + +## Wildcards + + The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`. + + You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:". + +## Browser support + + Debug works in the browser as well, currently persisted by `localStorage`. Consider the situation shown below where you have `worker:a` and `worker:b`, and wish to debug both. Somewhere in the code on your page, include: + +```js +window.myDebug = require("debug"); +``` + + ("debug" is a global object in the browser so we give this object a different name.) When your page is open in the browser, type the following in the console: + +```js +myDebug.enable("worker:*") +``` + + Refresh the page. Debug output will continue to be sent to the console until it is disabled by typing `myDebug.disable()` in the console. + +```js +a = debug('worker:a'); +b = debug('worker:b'); + +setInterval(function(){ + a('doing some work'); +}, 1000); + +setInterval(function(){ + b('doing some work'); +}, 1200); +``` + +#### Web Inspector Colors + + Colors are also enabled on "Web Inspectors" that understand the `%c` formatting + option. These are WebKit web inspectors, Firefox ([since version + 31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/)) + and the Firebug plugin for Firefox (any version). + + Colored output looks something like: + +  + +### stderr vs stdout + +You can set an alternative logging method per-namespace by overriding the `log` method on a per-namespace or globally: + +Example _stdout.js_: + +```js +var debug = require('debug'); +var error = debug('app:error'); + +// by default stderr is used +error('goes to stderr!'); + +var log = debug('app:log'); +// set this namespace to log via console.log +log.log = console.log.bind(console); // don't forget to bind to console! +log('goes to stdout'); +error('still goes to stderr!'); + +// set all output to go via console.info +// overrides all per-namespace log settings +debug.log = console.info.bind(console); +error('now goes to stdout via console.info'); +log('still goes to stdout, but via console.info now'); +``` + +### Save debug output to a file + +You can save all debug statements to a file by piping them. + +Example: + +```bash +$ DEBUG_FD=3 node your-app.js 3> whatever.log +``` + +## Authors + + - TJ Holowaychuk + - Nathan Rajlich + +## License + +(The MIT License) + +Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,28 @@
+{ + "name": "visionmedia-debug", + "main": "dist/debug.js", + "version": "2.2.0", + "homepage": "https://github.com/visionmedia/debug", + "authors": [ + "TJ Holowaychuk <tj@vision-media.ca>" + ], + "description": "visionmedia-debug", + "moduleType": [ + "amd", + "es6", + "globals", + "node" + ], + "keywords": [ + "visionmedia", + "debug" + ], + "license": "MIT", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ] +}
@@ -0,0 +1,168 @@
+ +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = require('./debug'); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = 'undefined' != typeof chrome + && 'undefined' != typeof chrome.storage + ? chrome.storage.local + : localstorage(); + +/** + * Colors. + */ + +exports.colors = [ + 'lightseagreen', + 'forestgreen', + 'goldenrod', + 'dodgerblue', + 'darkorchid', + 'crimson' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +function useColors() { + // is webkit? http://stackoverflow.com/a/16459606/376773 + return ('WebkitAppearance' in document.documentElement.style) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (window.console && (console.firebug || (console.exception && console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31); +} + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +exports.formatters.j = function(v) { + return JSON.stringify(v); +}; + + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs() { + var args = arguments; + var useColors = this.useColors; + + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); + + if (!useColors) return args; + + var c = 'color: ' + this.color; + args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); + + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-z%]/g, function(match) { + if ('%%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); + return args; +} + +/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + +function log() { + // this hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return 'object' === typeof console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + try { + if (null == namespaces) { + exports.storage.removeItem('debug'); + } else { + exports.storage.debug = namespaces; + } + } catch(e) {} +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + var r; + try { + r = exports.storage.debug; + } catch(e) {} + return r; +} + +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ + +exports.enable(load()); + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage(){ + try { + return window.localStorage; + } catch (e) {} +}
@@ -0,0 +1,19 @@
+{ + "name": "debug", + "repo": "visionmedia/debug", + "description": "small debugging utility", + "version": "2.2.0", + "keywords": [ + "debug", + "log", + "debugger" + ], + "main": "browser.js", + "scripts": [ + "browser.js", + "debug.js" + ], + "dependencies": { + "rauchg/ms.js": "0.7.1" + } +}
@@ -0,0 +1,197 @@
+ +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = debug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = require('ms'); + +/** + * The currently active debug mode names, and names to skip. + */ + +exports.names = []; +exports.skips = []; + +/** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lowercased letter, i.e. "n". + */ + +exports.formatters = {}; + +/** + * Previously assigned color. + */ + +var prevColor = 0; + +/** + * Previous log timestamp. + */ + +var prevTime; + +/** + * Select a color. + * + * @return {Number} + * @api private + */ + +function selectColor() { + return exports.colors[prevColor++ % exports.colors.length]; +} + +/** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + +function debug(namespace) { + + // define the `disabled` version + function disabled() { + } + disabled.enabled = false; + + // define the `enabled` version + function enabled() { + + var self = enabled; + + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + // add the `color` if not set + if (null == self.useColors) self.useColors = exports.useColors(); + if (null == self.color && self.useColors) self.color = selectColor(); + + var args = Array.prototype.slice.call(arguments); + + args[0] = exports.coerce(args[0]); + + if ('string' !== typeof args[0]) { + // anything else let's inspect with %o + args = ['%o'].concat(args); + } + + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + if ('function' === typeof exports.formatArgs) { + args = exports.formatArgs.apply(self, args); + } + var logFn = enabled.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } + enabled.enabled = true; + + var fn = exports.enabled(namespace) ? enabled : disabled; + + fn.namespace = namespace; + + return fn; +} + +/** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + +function enable(namespaces) { + exports.save(namespaces); + + var split = (namespaces || '').split(/[\s,]+/); + var len = split.length; + + for (var i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); + } + } +} + +/** + * Disable debug output. + * + * @api public + */ + +function disable() { + exports.enable(''); +} + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +function enabled(name) { + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; +} + +/** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; +}
@@ -0,0 +1,209 @@
+ +/** + * Module dependencies. + */ + +var tty = require('tty'); +var util = require('util'); + +/** + * This is the Node.js implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = require('./debug'); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; + +/** + * Colors. + */ + +exports.colors = [6, 2, 3, 4, 5, 1]; + +/** + * The file descriptor to write the `debug()` calls to. + * Set the `DEBUG_FD` env variable to override with another value. i.e.: + * + * $ DEBUG_FD=3 node script.js 3>debug.log + */ + +var fd = parseInt(process.env.DEBUG_FD, 10) || 2; +var stream = 1 === fd ? process.stdout : + 2 === fd ? process.stderr : + createWritableStdioStream(fd); + +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ + +function useColors() { + var debugColors = (process.env.DEBUG_COLORS || '').trim().toLowerCase(); + if (0 === debugColors.length) { + return tty.isatty(fd); + } else { + return '0' !== debugColors + && 'no' !== debugColors + && 'false' !== debugColors + && 'disabled' !== debugColors; + } +} + +/** + * Map %o to `util.inspect()`, since Node doesn't do that out of the box. + */ + +var inspect = (4 === util.inspect.length ? + // node <= 0.8.x + function (v, colors) { + return util.inspect(v, void 0, void 0, colors); + } : + // node > 0.8.x + function (v, colors) { + return util.inspect(v, { colors: colors }); + } +); + +exports.formatters.o = function(v) { + return inspect(v, this.useColors) + .replace(/\s*\n\s*/g, ' '); +}; + +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ + +function formatArgs() { + var args = arguments; + var useColors = this.useColors; + var name = this.namespace; + + if (useColors) { + var c = this.color; + + args[0] = ' \u001b[3' + c + ';1m' + name + ' ' + + '\u001b[0m' + + args[0] + '\u001b[3' + c + 'm' + + ' +' + exports.humanize(this.diff) + '\u001b[0m'; + } else { + args[0] = new Date().toUTCString() + + ' ' + name + ' ' + args[0]; + } + return args; +} + +/** + * Invokes `console.error()` with the specified arguments. + */ + +function log() { + return stream.write(util.format.apply(this, arguments) + '\n'); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + if (null == namespaces) { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } else { + process.env.DEBUG = namespaces; + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + return process.env.DEBUG; +} + +/** + * Copied from `node/src/node.js`. + * + * XXX: It's lame that node doesn't expose this API out-of-the-box. It also + * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame. + */ + +function createWritableStdioStream (fd) { + var stream; + var tty_wrap = process.binding('tty_wrap'); + + // Note stream._type is used for test-module-load-list.js + + switch (tty_wrap.guessHandleType(fd)) { + case 'TTY': + stream = new tty.WriteStream(fd); + stream._type = 'tty'; + + // Hack to have stream not keep the event loop alive. + // See https://github.com/joyent/node/issues/1726 + if (stream._handle && stream._handle.unref) { + stream._handle.unref(); + } + break; + + case 'FILE': + var fs = require('fs'); + stream = new fs.SyncWriteStream(fd, { autoClose: false }); + stream._type = 'fs'; + break; + + case 'PIPE': + case 'TCP': + var net = require('net'); + stream = new net.Socket({ + fd: fd, + readable: false, + writable: true + }); + + // FIXME Should probably have an option in net.Socket to create a + // stream from an existing fd which is writable only. But for now + // we'll just add this hack and set the `readable` member to false. + // Test: ./node test/fixtures/echo.js < /etc/passwd + stream.readable = false; + stream.read = null; + stream._type = 'pipe'; + + // FIXME Hack to have stream not keep the event loop alive. + // See https://github.com/joyent/node/issues/1726 + if (stream._handle && stream._handle.unref) { + stream._handle.unref(); + } + break; + + default: + // Probably an error on in uv_guess_handle() + throw new Error('Implement me. Unknown stream file type!'); + } + + // For supporting legacy API we put the FD here. + stream.fd = fd; + + stream._isStdio = true; + + return stream; +} + +/** + * Enable namespaces listed in `process.env.DEBUG` initially. + */ + +exports.enable(load());
@@ -0,0 +1,5 @@
+node_modules +test +History.md +Makefile +component.json
@@ -0,0 +1,66 @@
+ +0.7.1 / 2015-04-20 +================== + + * prevent extraordinary long inputs (@evilpacket) + * Fixed broken readme link + +0.7.0 / 2014-11-24 +================== + + * add time abbreviations, updated tests and readme for the new units + * fix example in the readme. + * add LICENSE file + +0.6.2 / 2013-12-05 +================== + + * Adding repository section to package.json to suppress warning from NPM. + +0.6.1 / 2013-05-10 +================== + + * fix singularization [visionmedia] + +0.6.0 / 2013-03-15 +================== + + * fix minutes + +0.5.1 / 2013-02-24 +================== + + * add component namespace + +0.5.0 / 2012-11-09 +================== + + * add short formatting as default and .long option + * add .license property to component.json + * add version to component.json + +0.4.0 / 2012-10-22 +================== + + * add rounding to fix crazy decimals + +0.3.0 / 2012-09-07 +================== + + * fix `ms(<String>)` [visionmedia] + +0.2.0 / 2012-09-03 +================== + + * add component.json [visionmedia] + * add days support [visionmedia] + * add hours support [visionmedia] + * add minutes support [visionmedia] + * add seconds support [visionmedia] + * add ms string support [visionmedia] + * refactor tests to facilitate ms(number) [visionmedia] + +0.1.0 / 2012-03-07 +================== + + * Initial release
@@ -0,0 +1,20 @@
+(The MIT License) + +Copyright (c) 2014 Guillermo Rauch <rauchg@gmail.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,35 @@
+# ms.js: miliseconds conversion utility + +```js +ms('2 days') // 172800000 +ms('1d') // 86400000 +ms('10h') // 36000000 +ms('2.5 hrs') // 9000000 +ms('2h') // 7200000 +ms('1m') // 60000 +ms('5s') // 5000 +ms('100') // 100 +``` + +```js +ms(60000) // "1m" +ms(2 * 60000) // "2m" +ms(ms('10 hours')) // "10h" +``` + +```js +ms(60000, { long: true }) // "1 minute" +ms(2 * 60000, { long: true }) // "2 minutes" +ms(ms('10 hours'), { long: true }) // "10 hours" +``` + +- Node/Browser compatible. Published as [`ms`](https://www.npmjs.org/package/ms) in [NPM](http://nodejs.org/download). +- If a number is supplied to `ms`, a string with a unit is returned. +- If a string that contains the number is supplied, it returns it as +a number (e.g: it returns `100` for `'100'`). +- If you pass a string with a number and a valid unit, the number of +equivalent ms is returned. + +## License + +MIT
@@ -0,0 +1,125 @@
+/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} options + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options){ + options = options || {}; + if ('string' == typeof val) return parse(val); + return options.long + ? long(val) + : short(val); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = '' + str; + if (str.length > 10000) return; + var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str); + if (!match) return; + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function short(ms) { + if (ms >= d) return Math.round(ms / d) + 'd'; + if (ms >= h) return Math.round(ms / h) + 'h'; + if (ms >= m) return Math.round(ms / m) + 'm'; + if (ms >= s) return Math.round(ms / s) + 's'; + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function long(ms) { + return plural(ms, d, 'day') + || plural(ms, h, 'hour') + || plural(ms, m, 'minute') + || plural(ms, s, 'second') + || ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, n, name) { + if (ms < n) return; + if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name; + return Math.ceil(ms / n) + ' ' + name + 's'; +}
@@ -0,0 +1,48 @@
+{ + "name": "ms", + "version": "0.7.1", + "description": "Tiny ms conversion utility", + "repository": { + "type": "git", + "url": "git://github.com/guille/ms.js.git" + }, + "main": "./index", + "devDependencies": { + "mocha": "*", + "expect.js": "*", + "serve": "*" + }, + "component": { + "scripts": { + "ms/index.js": "index.js" + } + }, + "gitHead": "713dcf26d9e6fd9dbc95affe7eff9783b7f1b909", + "bugs": { + "url": "https://github.com/guille/ms.js/issues" + }, + "homepage": "https://github.com/guille/ms.js", + "_id": "ms@0.7.1", + "scripts": {}, + "_shasum": "9cd13c03adbff25b65effde7ce864ee952017098", + "_from": "ms@0.7.1", + "_npmVersion": "2.7.5", + "_nodeVersion": "0.12.2", + "_npmUser": { + "name": "rauchg", + "email": "rauchg@gmail.com" + }, + "maintainers": [ + { + "name": "rauchg", + "email": "rauchg@gmail.com" + } + ], + "dist": { + "shasum": "9cd13c03adbff25b65effde7ce864ee952017098", + "tarball": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,73 @@
+{ + "name": "debug", + "version": "2.2.0", + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/debug.git" + }, + "description": "small debugging utility", + "keywords": [ + "debug", + "log", + "debugger" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "contributors": [ + { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "http://n8.io" + } + ], + "license": "MIT", + "dependencies": { + "ms": "0.7.1" + }, + "devDependencies": { + "browserify": "9.0.3", + "mocha": "*" + }, + "main": "./node.js", + "browser": "./browser.js", + "component": { + "scripts": { + "debug/index.js": "browser.js", + "debug/debug.js": "debug.js" + } + }, + "gitHead": "b38458422b5aa8aa6d286b10dfe427e8a67e2b35", + "bugs": { + "url": "https://github.com/visionmedia/debug/issues" + }, + "homepage": "https://github.com/visionmedia/debug", + "_id": "debug@2.2.0", + "scripts": {}, + "_shasum": "f87057e995b1a1f6ae6a4960664137bc56f039da", + "_from": "debug@>=2.2.0 <2.3.0", + "_npmVersion": "2.7.4", + "_nodeVersion": "0.12.2", + "_npmUser": { + "name": "tootallnate", + "email": "nathan@tootallnate.net" + }, + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + { + "name": "tootallnate", + "email": "nathan@tootallnate.net" + } + ], + "dist": { + "shasum": "f87057e995b1a1f6ae6a4960664137bc56f039da", + "tarball": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,84 @@
+1.1.0 / 2015-09-14 +================== + + * Enable strict mode in more places + * Support io.js 3.x + * Support io.js 2.x + * Support web browser loading + - Requires bundler like Browserify or webpack + +1.0.1 / 2015-04-07 +================== + + * Fix `TypeError`s when under `'use strict'` code + * Fix useless type name on auto-generated messages + * Support io.js 1.x + * Support Node.js 0.12 + +1.0.0 / 2014-09-17 +================== + + * No changes + +0.4.5 / 2014-09-09 +================== + + * Improve call speed to functions using the function wrapper + * Support Node.js 0.6 + +0.4.4 / 2014-07-27 +================== + + * Work-around v8 generating empty stack traces + +0.4.3 / 2014-07-26 +================== + + * Fix exception when global `Error.stackTraceLimit` is too low + +0.4.2 / 2014-07-19 +================== + + * Correct call site for wrapped functions and properties + +0.4.1 / 2014-07-19 +================== + + * Improve automatic message generation for function properties + +0.4.0 / 2014-07-19 +================== + + * Add `TRACE_DEPRECATION` environment variable + * Remove non-standard grey color from color output + * Support `--no-deprecation` argument + * Support `--trace-deprecation` argument + * Support `deprecate.property(fn, prop, message)` + +0.3.0 / 2014-06-16 +================== + + * Add `NO_DEPRECATION` environment variable + +0.2.0 / 2014-06-15 +================== + + * Add `deprecate.property(obj, prop, message)` + * Remove `supports-color` dependency for node.js 0.8 + +0.1.0 / 2014-06-15 +================== + + * Add `deprecate.function(fn, message)` + * Add `process.on('deprecation', fn)` emitter + * Automatically generate message when omitted from `deprecate()` + +0.0.1 / 2014-06-15 +================== + + * Fix warning for dynamic calls at singe call site + +0.0.0 / 2014-06-15 +================== + + * Initial implementation
@@ -0,0 +1,22 @@
+(The MIT License) + +Copyright (c) 2014-2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,281 @@
+# depd + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Node.js Version][node-image]][node-url] +[![Linux Build][travis-image]][travis-url] +[![Windows Build][appveyor-image]][appveyor-url] +[![Coverage Status][coveralls-image]][coveralls-url] +[![Gratipay][gratipay-image]][gratipay-url] + +Deprecate all the things + +> With great modules comes great responsibility; mark things deprecated! + +## Install + +This module is installed directly using `npm`: + +```sh +$ npm install depd +``` + +This module can also be bundled with systems like +[Browserify](http://browserify.org/) or [webpack](https://webpack.github.io/), +though by default this module will alter it's API to no longer display or +track deprecations. + +## API + +```js +var deprecate = require('depd')('my-module') +``` + +This library allows you to display deprecation messages to your users. +This library goes above and beyond with deprecation warnings by +introspection of the call stack (but only the bits that it is interested +in). + +Instead of just warning on the first invocation of a deprecated +function and never again, this module will warn on the first invocation +of a deprecated function per unique call site, making it ideal to alert +users of all deprecated uses across the code base, rather than just +whatever happens to execute first. + +The deprecation warnings from this module also include the file and line +information for the call into the module that the deprecated function was +in. + +**NOTE** this library has a similar interface to the `debug` module, and +this module uses the calling file to get the boundary for the call stacks, +so you should always create a new `deprecate` object in each file and not +within some central file. + +### depd(namespace) + +Create a new deprecate function that uses the given namespace name in the +messages and will display the call site prior to the stack entering the +file this function was called from. It is highly suggested you use the +name of your module as the namespace. + +### deprecate(message) + +Call this function from deprecated code to display a deprecation message. +This message will appear once per unique caller site. Caller site is the +first call site in the stack in a different file from the caller of this +function. + +If the message is omitted, a message is generated for you based on the site +of the `deprecate()` call and will display the name of the function called, +similar to the name displayed in a stack trace. + +### deprecate.function(fn, message) + +Call this function to wrap a given function in a deprecation message on any +call to the function. An optional message can be supplied to provide a custom +message. + +### deprecate.property(obj, prop, message) + +Call this function to wrap a given property on object in a deprecation message +on any accessing or setting of the property. An optional message can be supplied +to provide a custom message. + +The method must be called on the object where the property belongs (not +inherited from the prototype). + +If the property is a data descriptor, it will be converted to an accessor +descriptor in order to display the deprecation message. + +### process.on('deprecation', fn) + +This module will allow easy capturing of deprecation errors by emitting the +errors as the type "deprecation" on the global `process`. If there are no +listeners for this type, the errors are written to STDERR as normal, but if +there are any listeners, nothing will be written to STDERR and instead only +emitted. From there, you can write the errors in a different format or to a +logging source. + +The error represents the deprecation and is emitted only once with the same +rules as writing to STDERR. The error has the following properties: + + - `message` - This is the message given by the library + - `name` - This is always `'DeprecationError'` + - `namespace` - This is the namespace the deprecation came from + - `stack` - This is the stack of the call to the deprecated thing + +Example `error.stack` output: + +``` +DeprecationError: my-cool-module deprecated oldfunction + at Object.<anonymous> ([eval]-wrapper:6:22) + at Module._compile (module.js:456:26) + at evalScript (node.js:532:25) + at startup (node.js:80:7) + at node.js:902:3 +``` + +### process.env.NO_DEPRECATION + +As a user of modules that are deprecated, the environment variable `NO_DEPRECATION` +is provided as a quick solution to silencing deprecation warnings from being +output. The format of this is similar to that of `DEBUG`: + +```sh +$ NO_DEPRECATION=my-module,othermod node app.js +``` + +This will suppress deprecations from being output for "my-module" and "othermod". +The value is a list of comma-separated namespaces. To suppress every warning +across all namespaces, use the value `*` for a namespace. + +Providing the argument `--no-deprecation` to the `node` executable will suppress +all deprecations (only available in Node.js 0.8 or higher). + +**NOTE** This will not suppress the deperecations given to any "deprecation" +event listeners, just the output to STDERR. + +### process.env.TRACE_DEPRECATION + +As a user of modules that are deprecated, the environment variable `TRACE_DEPRECATION` +is provided as a solution to getting more detailed location information in deprecation +warnings by including the entire stack trace. The format of this is the same as +`NO_DEPRECATION`: + +```sh +$ TRACE_DEPRECATION=my-module,othermod node app.js +``` + +This will include stack traces for deprecations being output for "my-module" and +"othermod". The value is a list of comma-separated namespaces. To trace every +warning across all namespaces, use the value `*` for a namespace. + +Providing the argument `--trace-deprecation` to the `node` executable will trace +all deprecations (only available in Node.js 0.8 or higher). + +**NOTE** This will not trace the deperecations silenced by `NO_DEPRECATION`. + +## Display + + + +When a user calls a function in your library that you mark deprecated, they +will see the following written to STDERR (in the given colors, similar colors +and layout to the `debug` module): + +``` +bright cyan bright yellow +| | reset cyan +| | | | +▼ ▼ ▼ ▼ +my-cool-module deprecated oldfunction [eval]-wrapper:6:22 +▲ ▲ ▲ ▲ +| | | | +namespace | | location of mycoolmod.oldfunction() call + | deprecation message + the word "deprecated" +``` + +If the user redirects their STDERR to a file or somewhere that does not support +colors, they see (similar layout to the `debug` module): + +``` +Sun, 15 Jun 2014 05:21:37 GMT my-cool-module deprecated oldfunction at [eval]-wrapper:6:22 +▲ ▲ ▲ ▲ ▲ +| | | | | +timestamp of message namespace | | location of mycoolmod.oldfunction() call + | deprecation message + the word "deprecated" +``` + +## Examples + +### Deprecating all calls to a function + +This will display a deprecated message about "oldfunction" being deprecated +from "my-module" on STDERR. + +```js +var deprecate = require('depd')('my-cool-module') + +// message automatically derived from function name +// Object.oldfunction +exports.oldfunction = deprecate.function(function oldfunction() { + // all calls to function are deprecated +}) + +// specific message +exports.oldfunction = deprecate.function(function () { + // all calls to function are deprecated +}, 'oldfunction') +``` + +### Conditionally deprecating a function call + +This will display a deprecated message about "weirdfunction" being deprecated +from "my-module" on STDERR when called with less than 2 arguments. + +```js +var deprecate = require('depd')('my-cool-module') + +exports.weirdfunction = function () { + if (arguments.length < 2) { + // calls with 0 or 1 args are deprecated + deprecate('weirdfunction args < 2') + } +} +``` + +When calling `deprecate` as a function, the warning is counted per call site +within your own module, so you can display different deprecations depending +on different situations and the users will still get all the warnings: + +```js +var deprecate = require('depd')('my-cool-module') + +exports.weirdfunction = function () { + if (arguments.length < 2) { + // calls with 0 or 1 args are deprecated + deprecate('weirdfunction args < 2') + } else if (typeof arguments[0] !== 'string') { + // calls with non-string first argument are deprecated + deprecate('weirdfunction non-string first arg') + } +} +``` + +### Deprecating property access + +This will display a deprecated message about "oldprop" being deprecated +from "my-module" on STDERR when accessed. A deprecation will be displayed +when setting the value and when getting the value. + +```js +var deprecate = require('depd')('my-cool-module') + +exports.oldprop = 'something' + +// message automatically derives from property name +deprecate.property(exports, 'oldprop') + +// explicit message +deprecate.property(exports, 'oldprop', 'oldprop >= 0.10') +``` + +## License + +[MIT](LICENSE) + +[npm-version-image]: https://img.shields.io/npm/v/depd.svg +[npm-downloads-image]: https://img.shields.io/npm/dm/depd.svg +[npm-url]: https://npmjs.org/package/depd +[travis-image]: https://img.shields.io/travis/dougwilson/nodejs-depd/master.svg?label=linux +[travis-url]: https://travis-ci.org/dougwilson/nodejs-depd +[appveyor-image]: https://img.shields.io/appveyor/ci/dougwilson/nodejs-depd/master.svg?label=windows +[appveyor-url]: https://ci.appveyor.com/project/dougwilson/nodejs-depd +[coveralls-image]: https://img.shields.io/coveralls/dougwilson/nodejs-depd/master.svg +[coveralls-url]: https://coveralls.io/r/dougwilson/nodejs-depd?branch=master +[node-image]: https://img.shields.io/node/v/depd.svg +[node-url]: http://nodejs.org/download/ +[gratipay-image]: https://img.shields.io/gratipay/dougwilson.svg +[gratipay-url]: https://www.gratipay.com/dougwilson/
@@ -0,0 +1,521 @@
+/*! + * depd + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var callSiteToString = require('./lib/compat').callSiteToString +var eventListenerCount = require('./lib/compat').eventListenerCount +var relative = require('path').relative + +/** + * Module exports. + */ + +module.exports = depd + +/** + * Get the path to base files on. + */ + +var basePath = process.cwd() + +/** + * Determine if namespace is contained in the string. + */ + +function containsNamespace(str, namespace) { + var val = str.split(/[ ,]+/) + + namespace = String(namespace).toLowerCase() + + for (var i = 0 ; i < val.length; i++) { + if (!(str = val[i])) continue; + + // namespace contained + if (str === '*' || str.toLowerCase() === namespace) { + return true + } + } + + return false +} + +/** + * Convert a data descriptor to accessor descriptor. + */ + +function convertDataDescriptorToAccessor(obj, prop, message) { + var descriptor = Object.getOwnPropertyDescriptor(obj, prop) + var value = descriptor.value + + descriptor.get = function getter() { return value } + + if (descriptor.writable) { + descriptor.set = function setter(val) { return value = val } + } + + delete descriptor.value + delete descriptor.writable + + Object.defineProperty(obj, prop, descriptor) + + return descriptor +} + +/** + * Create arguments string to keep arity. + */ + +function createArgumentsString(arity) { + var str = '' + + for (var i = 0; i < arity; i++) { + str += ', arg' + i + } + + return str.substr(2) +} + +/** + * Create stack string from stack. + */ + +function createStackString(stack) { + var str = this.name + ': ' + this.namespace + + if (this.message) { + str += ' deprecated ' + this.message + } + + for (var i = 0; i < stack.length; i++) { + str += '\n at ' + callSiteToString(stack[i]) + } + + return str +} + +/** + * Create deprecate for namespace in caller. + */ + +function depd(namespace) { + if (!namespace) { + throw new TypeError('argument namespace is required') + } + + var stack = getStack() + var site = callSiteLocation(stack[1]) + var file = site[0] + + function deprecate(message) { + // call to self as log + log.call(deprecate, message) + } + + deprecate._file = file + deprecate._ignored = isignored(namespace) + deprecate._namespace = namespace + deprecate._traced = istraced(namespace) + deprecate._warned = Object.create(null) + + deprecate.function = wrapfunction + deprecate.property = wrapproperty + + return deprecate +} + +/** + * Determine if namespace is ignored. + */ + +function isignored(namespace) { + /* istanbul ignore next: tested in a child processs */ + if (process.noDeprecation) { + // --no-deprecation support + return true + } + + var str = process.env.NO_DEPRECATION || '' + + // namespace ignored + return containsNamespace(str, namespace) +} + +/** + * Determine if namespace is traced. + */ + +function istraced(namespace) { + /* istanbul ignore next: tested in a child processs */ + if (process.traceDeprecation) { + // --trace-deprecation support + return true + } + + var str = process.env.TRACE_DEPRECATION || '' + + // namespace traced + return containsNamespace(str, namespace) +} + +/** + * Display deprecation message. + */ + +function log(message, site) { + var haslisteners = eventListenerCount(process, 'deprecation') !== 0 + + // abort early if no destination + if (!haslisteners && this._ignored) { + return + } + + var caller + var callFile + var callSite + var i = 0 + var seen = false + var stack = getStack() + var file = this._file + + if (site) { + // provided site + callSite = callSiteLocation(stack[1]) + callSite.name = site.name + file = callSite[0] + } else { + // get call site + i = 2 + site = callSiteLocation(stack[i]) + callSite = site + } + + // get caller of deprecated thing in relation to file + for (; i < stack.length; i++) { + caller = callSiteLocation(stack[i]) + callFile = caller[0] + + if (callFile === file) { + seen = true + } else if (callFile === this._file) { + file = this._file + } else if (seen) { + break + } + } + + var key = caller + ? site.join(':') + '__' + caller.join(':') + : undefined + + if (key !== undefined && key in this._warned) { + // already warned + return + } + + this._warned[key] = true + + // generate automatic message from call site + if (!message) { + message = callSite === site || !callSite.name + ? defaultMessage(site) + : defaultMessage(callSite) + } + + // emit deprecation if listeners exist + if (haslisteners) { + var err = DeprecationError(this._namespace, message, stack.slice(i)) + process.emit('deprecation', err) + return + } + + // format and write message + var format = process.stderr.isTTY + ? formatColor + : formatPlain + var msg = format.call(this, message, caller, stack.slice(i)) + process.stderr.write(msg + '\n', 'utf8') + + return +} + +/** + * Get call site location as array. + */ + +function callSiteLocation(callSite) { + var file = callSite.getFileName() || '<anonymous>' + var line = callSite.getLineNumber() + var colm = callSite.getColumnNumber() + + if (callSite.isEval()) { + file = callSite.getEvalOrigin() + ', ' + file + } + + var site = [file, line, colm] + + site.callSite = callSite + site.name = callSite.getFunctionName() + + return site +} + +/** + * Generate a default message from the site. + */ + +function defaultMessage(site) { + var callSite = site.callSite + var funcName = site.name + + // make useful anonymous name + if (!funcName) { + funcName = '<anonymous@' + formatLocation(site) + '>' + } + + var context = callSite.getThis() + var typeName = context && callSite.getTypeName() + + // ignore useless type name + if (typeName === 'Object') { + typeName = undefined + } + + // make useful type name + if (typeName === 'Function') { + typeName = context.name || typeName + } + + return typeName && callSite.getMethodName() + ? typeName + '.' + funcName + : funcName +} + +/** + * Format deprecation message without color. + */ + +function formatPlain(msg, caller, stack) { + var timestamp = new Date().toUTCString() + + var formatted = timestamp + + ' ' + this._namespace + + ' deprecated ' + msg + + // add stack trace + if (this._traced) { + for (var i = 0; i < stack.length; i++) { + formatted += '\n at ' + callSiteToString(stack[i]) + } + + return formatted + } + + if (caller) { + formatted += ' at ' + formatLocation(caller) + } + + return formatted +} + +/** + * Format deprecation message with color. + */ + +function formatColor(msg, caller, stack) { + var formatted = '\x1b[36;1m' + this._namespace + '\x1b[22;39m' // bold cyan + + ' \x1b[33;1mdeprecated\x1b[22;39m' // bold yellow + + ' \x1b[0m' + msg + '\x1b[39m' // reset + + // add stack trace + if (this._traced) { + for (var i = 0; i < stack.length; i++) { + formatted += '\n \x1b[36mat ' + callSiteToString(stack[i]) + '\x1b[39m' // cyan + } + + return formatted + } + + if (caller) { + formatted += ' \x1b[36m' + formatLocation(caller) + '\x1b[39m' // cyan + } + + return formatted +} + +/** + * Format call site location. + */ + +function formatLocation(callSite) { + return relative(basePath, callSite[0]) + + ':' + callSite[1] + + ':' + callSite[2] +} + +/** + * Get the stack as array of call sites. + */ + +function getStack() { + var limit = Error.stackTraceLimit + var obj = {} + var prep = Error.prepareStackTrace + + Error.prepareStackTrace = prepareObjectStackTrace + Error.stackTraceLimit = Math.max(10, limit) + + // capture the stack + Error.captureStackTrace(obj) + + // slice this function off the top + var stack = obj.stack.slice(1) + + Error.prepareStackTrace = prep + Error.stackTraceLimit = limit + + return stack +} + +/** + * Capture call site stack from v8. + */ + +function prepareObjectStackTrace(obj, stack) { + return stack +} + +/** + * Return a wrapped function in a deprecation message. + */ + +function wrapfunction(fn, message) { + if (typeof fn !== 'function') { + throw new TypeError('argument fn must be a function') + } + + var args = createArgumentsString(fn.length) + var deprecate = this + var stack = getStack() + var site = callSiteLocation(stack[1]) + + site.name = fn.name + + var deprecatedfn = eval('(function (' + args + ') {\n' + + '"use strict"\n' + + 'log.call(deprecate, message, site)\n' + + 'return fn.apply(this, arguments)\n' + + '})') + + return deprecatedfn +} + +/** + * Wrap property in a deprecation message. + */ + +function wrapproperty(obj, prop, message) { + if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) { + throw new TypeError('argument obj must be object') + } + + var descriptor = Object.getOwnPropertyDescriptor(obj, prop) + + if (!descriptor) { + throw new TypeError('must call property on owner object') + } + + if (!descriptor.configurable) { + throw new TypeError('property must be configurable') + } + + var deprecate = this + var stack = getStack() + var site = callSiteLocation(stack[1]) + + // set site name + site.name = prop + + // convert data descriptor + if ('value' in descriptor) { + descriptor = convertDataDescriptorToAccessor(obj, prop, message) + } + + var get = descriptor.get + var set = descriptor.set + + // wrap getter + if (typeof get === 'function') { + descriptor.get = function getter() { + log.call(deprecate, message, site) + return get.apply(this, arguments) + } + } + + // wrap setter + if (typeof set === 'function') { + descriptor.set = function setter() { + log.call(deprecate, message, site) + return set.apply(this, arguments) + } + } + + Object.defineProperty(obj, prop, descriptor) +} + +/** + * Create DeprecationError for deprecation + */ + +function DeprecationError(namespace, message, stack) { + var error = new Error() + var stackString + + Object.defineProperty(error, 'constructor', { + value: DeprecationError + }) + + Object.defineProperty(error, 'message', { + configurable: true, + enumerable: false, + value: message, + writable: true + }) + + Object.defineProperty(error, 'name', { + enumerable: false, + configurable: true, + value: 'DeprecationError', + writable: true + }) + + Object.defineProperty(error, 'namespace', { + configurable: true, + enumerable: false, + value: namespace, + writable: true + }) + + Object.defineProperty(error, 'stack', { + configurable: true, + enumerable: false, + get: function () { + if (stackString !== undefined) { + return stackString + } + + // prepare stack trace + return stackString = createStackString.call(this, stack) + }, + set: function setter(val) { + stackString = val + } + }) + + return error +}
@@ -0,0 +1,79 @@
+/*! + * depd + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = depd + +/** + * Create deprecate for namespace in caller. + */ + +function depd(namespace) { + if (!namespace) { + throw new TypeError('argument namespace is required') + } + + function deprecate(message) { + // no-op in browser + } + + deprecate._file = undefined + deprecate._ignored = true + deprecate._namespace = namespace + deprecate._traced = false + deprecate._warned = Object.create(null) + + deprecate.function = wrapfunction + deprecate.property = wrapproperty + + return deprecate +} + +/** + * Return a wrapped function in a deprecation message. + * + * This is a no-op version of the wrapper, which does nothing but call + * validation. + */ + +function wrapfunction(fn, message) { + if (typeof fn !== 'function') { + throw new TypeError('argument fn must be a function') + } + + return fn +} + +/** + * Wrap property in a deprecation message. + * + * This is a no-op version of the wrapper, which does nothing but call + * validation. + */ + +function wrapproperty(obj, prop, message) { + if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) { + throw new TypeError('argument obj must be object') + } + + var descriptor = Object.getOwnPropertyDescriptor(obj, prop) + + if (!descriptor) { + throw new TypeError('must call property on owner object') + } + + if (!descriptor.configurable) { + throw new TypeError('property must be configurable') + } + + return +}
@@ -0,0 +1,35 @@
+/*! + * depd + * Copyright(c) 2014 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + */ + +module.exports = bufferConcat + +/** + * Concatenate an array of Buffers. + */ + +function bufferConcat(bufs) { + var length = 0 + + for (var i = 0, len = bufs.length; i < len; i++) { + length += bufs[i].length + } + + var buf = new Buffer(length) + var pos = 0 + + for (var i = 0, len = bufs.length; i < len; i++) { + bufs[i].copy(buf, pos) + pos += bufs[i].length + } + + return buf +}
@@ -0,0 +1,103 @@
+/*! + * depd + * Copyright(c) 2014 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + */ + +module.exports = callSiteToString + +/** + * Format a CallSite file location to a string. + */ + +function callSiteFileLocation(callSite) { + var fileName + var fileLocation = '' + + if (callSite.isNative()) { + fileLocation = 'native' + } else if (callSite.isEval()) { + fileName = callSite.getScriptNameOrSourceURL() + if (!fileName) { + fileLocation = callSite.getEvalOrigin() + } + } else { + fileName = callSite.getFileName() + } + + if (fileName) { + fileLocation += fileName + + var lineNumber = callSite.getLineNumber() + if (lineNumber != null) { + fileLocation += ':' + lineNumber + + var columnNumber = callSite.getColumnNumber() + if (columnNumber) { + fileLocation += ':' + columnNumber + } + } + } + + return fileLocation || 'unknown source' +} + +/** + * Format a CallSite to a string. + */ + +function callSiteToString(callSite) { + var addSuffix = true + var fileLocation = callSiteFileLocation(callSite) + var functionName = callSite.getFunctionName() + var isConstructor = callSite.isConstructor() + var isMethodCall = !(callSite.isToplevel() || isConstructor) + var line = '' + + if (isMethodCall) { + var methodName = callSite.getMethodName() + var typeName = getConstructorName(callSite) + + if (functionName) { + if (typeName && functionName.indexOf(typeName) !== 0) { + line += typeName + '.' + } + + line += functionName + + if (methodName && functionName.lastIndexOf('.' + methodName) !== functionName.length - methodName.length - 1) { + line += ' [as ' + methodName + ']' + } + } else { + line += typeName + '.' + (methodName || '<anonymous>') + } + } else if (isConstructor) { + line += 'new ' + (functionName || '<anonymous>') + } else if (functionName) { + line += functionName + } else { + addSuffix = false + line += fileLocation + } + + if (addSuffix) { + line += ' (' + fileLocation + ')' + } + + return line +} + +/** + * Get constructor name of reviver. + */ + +function getConstructorName(obj) { + var receiver = obj.receiver + return (receiver.constructor && receiver.constructor.name) || null +}
@@ -0,0 +1,22 @@
+/*! + * depd + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = eventListenerCount + +/** + * Get the count of listeners on an event emitter of a specific type. + */ + +function eventListenerCount(emitter, type) { + return emitter.listeners(type).length +}
@@ -0,0 +1,84 @@
+/*! + * depd + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var Buffer = require('buffer') +var EventEmitter = require('events').EventEmitter + +/** + * Module exports. + * @public + */ + +lazyProperty(module.exports, 'bufferConcat', function bufferConcat() { + return Buffer.concat || require('./buffer-concat') +}) + +lazyProperty(module.exports, 'callSiteToString', function callSiteToString() { + var limit = Error.stackTraceLimit + var obj = {} + var prep = Error.prepareStackTrace + + function prepareObjectStackTrace(obj, stack) { + return stack + } + + Error.prepareStackTrace = prepareObjectStackTrace + Error.stackTraceLimit = 2 + + // capture the stack + Error.captureStackTrace(obj) + + // slice the stack + var stack = obj.stack.slice() + + Error.prepareStackTrace = prep + Error.stackTraceLimit = limit + + return stack[0].toString ? toString : require('./callsite-tostring') +}) + +lazyProperty(module.exports, 'eventListenerCount', function eventListenerCount() { + return EventEmitter.listenerCount || require('./event-listener-count') +}) + +/** + * Define a lazy property. + */ + +function lazyProperty(obj, prop, getter) { + function get() { + var val = getter() + + Object.defineProperty(obj, prop, { + configurable: true, + enumerable: true, + value: val + }) + + return val + } + + Object.defineProperty(obj, prop, { + configurable: true, + enumerable: true, + get: get + }) +} + +/** + * Call toString() on the obj + */ + +function toString(obj) { + return obj.toString() +}
@@ -0,0 +1,67 @@
+{ + "name": "depd", + "description": "Deprecate all the things", + "version": "1.1.0", + "author": { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + "license": "MIT", + "keywords": [ + "deprecate", + "deprecated" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/dougwilson/nodejs-depd.git" + }, + "browser": "lib/browser/index.js", + "devDependencies": { + "benchmark": "1.0.0", + "beautify-benchmark": "0.2.4", + "istanbul": "0.3.5", + "mocha": "~1.21.5" + }, + "files": [ + "lib/", + "History.md", + "LICENSE", + "index.js", + "Readme.md" + ], + "engines": { + "node": ">= 0.6" + }, + "scripts": { + "bench": "node benchmark/index.js", + "test": "mocha --reporter spec --bail test/", + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --no-exit test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot test/" + }, + "gitHead": "78c659de20283e3a6bee92bda455e6daff01686a", + "bugs": { + "url": "https://github.com/dougwilson/nodejs-depd/issues" + }, + "homepage": "https://github.com/dougwilson/nodejs-depd", + "_id": "depd@1.1.0", + "_shasum": "e1bd82c6aab6ced965b97b88b17ed3e528ca18c3", + "_from": "depd@>=1.1.0 <1.2.0", + "_npmVersion": "1.4.28", + "_npmUser": { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "dist": { + "shasum": "e1bd82c6aab6ced965b97b88b17ed3e528ca18c3", + "tarball": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,88 @@
+2.3.0 / 2015-05-26 +================== + + * Add defined behavior for HTTP `CONNECT` requests + * Add defined behavior for HTTP `Upgrade` requests + * deps: ee-first@1.1.1 + +2.2.1 / 2015-04-22 +================== + + * Fix `isFinished(req)` when data buffered + +2.2.0 / 2014-12-22 +================== + + * Add message object to callback arguments + +2.1.1 / 2014-10-22 +================== + + * Fix handling of pipelined requests + +2.1.0 / 2014-08-16 +================== + + * Check if `socket` is detached + * Return `undefined` for `isFinished` if state unknown + +2.0.0 / 2014-08-16 +================== + + * Add `isFinished` function + * Move to `jshttp` organization + * Remove support for plain socket argument + * Rename to `on-finished` + * Support both `req` and `res` as arguments + * deps: ee-first@1.0.5 + +1.2.2 / 2014-06-10 +================== + + * Reduce listeners added to emitters + - avoids "event emitter leak" warnings when used multiple times on same request + +1.2.1 / 2014-06-08 +================== + + * Fix returned value when already finished + +1.2.0 / 2014-06-05 +================== + + * Call callback when called on already-finished socket + +1.1.4 / 2014-05-27 +================== + + * Support node.js 0.8 + +1.1.3 / 2014-04-30 +================== + + * Make sure errors passed as instanceof `Error` + +1.1.2 / 2014-04-18 +================== + + * Default the `socket` to passed-in object + +1.1.1 / 2014-01-16 +================== + + * Rename module to `finished` + +1.1.0 / 2013-12-25 +================== + + * Call callback when called on already-errored socket + +1.0.1 / 2013-12-20 +================== + + * Actually pass the error to the callback + +1.0.0 / 2013-12-20 +================== + + * Initial release
@@ -0,0 +1,23 @@
+(The MIT License) + +Copyright (c) 2013 Jonathan Ong <me@jongleberry.com> +Copyright (c) 2014 Douglas Christopher Wilson <doug@somethingdoug.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,154 @@
+# on-finished + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Execute a callback when a HTTP request closes, finishes, or errors. + +## Install + +```sh +$ npm install on-finished +``` + +## API + +```js +var onFinished = require('on-finished') +``` + +### onFinished(res, listener) + +Attach a listener to listen for the response to finish. The listener will +be invoked only once when the response finished. If the response finished +to an error, the first argument will contain the error. If the response +has already finished, the listener will be invoked. + +Listening to the end of a response would be used to close things associated +with the response, like open files. + +Listener is invoked as `listener(err, res)`. + +```js +onFinished(res, function (err, res) { + // clean up open fds, etc. + // err contains the error is request error'd +}) +``` + +### onFinished(req, listener) + +Attach a listener to listen for the request to finish. The listener will +be invoked only once when the request finished. If the request finished +to an error, the first argument will contain the error. If the request +has already finished, the listener will be invoked. + +Listening to the end of a request would be used to know when to continue +after reading the data. + +Listener is invoked as `listener(err, req)`. + +```js +var data = '' + +req.setEncoding('utf8') +res.on('data', function (str) { + data += str +}) + +onFinished(req, function (err, req) { + // data is read unless there is err +}) +``` + +### onFinished.isFinished(res) + +Determine if `res` is already finished. This would be useful to check and +not even start certain operations if the response has already finished. + +### onFinished.isFinished(req) + +Determine if `req` is already finished. This would be useful to check and +not even start certain operations if the request has already finished. + +## Special Node.js requests + +### HTTP CONNECT method + +The meaning of the `CONNECT` method from RFC 7231, section 4.3.6: + +> The CONNECT method requests that the recipient establish a tunnel to +> the destination origin server identified by the request-target and, +> if successful, thereafter restrict its behavior to blind forwarding +> of packets, in both directions, until the tunnel is closed. Tunnels +> are commonly used to create an end-to-end virtual connection, through +> one or more proxies, which can then be secured using TLS (Transport +> Layer Security, [RFC5246]). + +In Node.js, these request objects come from the `'connect'` event on +the HTTP server. + +When this module is used on a HTTP `CONNECT` request, the request is +considered "finished" immediately, **due to limitations in the Node.js +interface**. This means if the `CONNECT` request contains a request entity, +the request will be considered "finished" even before it has been read. + +There is no such thing as a response object to a `CONNECT` request in +Node.js, so there is no support for for one. + +### HTTP Upgrade request + +The meaning of the `Upgrade` header from RFC 7230, section 6.1: + +> The "Upgrade" header field is intended to provide a simple mechanism +> for transitioning from HTTP/1.1 to some other protocol on the same +> connection. + +In Node.js, these request objects come from the `'upgrade'` event on +the HTTP server. + +When this module is used on a HTTP request with an `Upgrade` header, the +request is considered "finished" immediately, **due to limitations in the +Node.js interface**. This means if the `Upgrade` request contains a request +entity, the request will be considered "finished" even before it has been +read. + +There is no such thing as a response object to a `Upgrade` request in +Node.js, so there is no support for for one. + +## Example + +The following code ensures that file descriptors are always closed +once the response finishes. + +```js +var destroy = require('destroy') +var http = require('http') +var onFinished = require('on-finished') + +http.createServer(function onRequest(req, res) { + var stream = fs.createReadStream('package.json') + stream.pipe(res) + onFinished(res, function (err) { + destroy(stream) + }) +}) +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/on-finished.svg +[npm-url]: https://npmjs.org/package/on-finished +[node-version-image]: https://img.shields.io/node/v/on-finished.svg +[node-version-url]: http://nodejs.org/download/ +[travis-image]: https://img.shields.io/travis/jshttp/on-finished/master.svg +[travis-url]: https://travis-ci.org/jshttp/on-finished +[coveralls-image]: https://img.shields.io/coveralls/jshttp/on-finished/master.svg +[coveralls-url]: https://coveralls.io/r/jshttp/on-finished?branch=master +[downloads-image]: https://img.shields.io/npm/dm/on-finished.svg +[downloads-url]: https://npmjs.org/package/on-finished
@@ -0,0 +1,196 @@
+/*! + * on-finished + * Copyright(c) 2013 Jonathan Ong + * Copyright(c) 2014 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = onFinished +module.exports.isFinished = isFinished + +/** + * Module dependencies. + * @private + */ + +var first = require('ee-first') + +/** + * Variables. + * @private + */ + +/* istanbul ignore next */ +var defer = typeof setImmediate === 'function' + ? setImmediate + : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) } + +/** + * Invoke callback when the response has finished, useful for + * cleaning up resources afterwards. + * + * @param {object} msg + * @param {function} listener + * @return {object} + * @public + */ + +function onFinished(msg, listener) { + if (isFinished(msg) !== false) { + defer(listener, null, msg) + return msg + } + + // attach the listener to the message + attachListener(msg, listener) + + return msg +} + +/** + * Determine if message is already finished. + * + * @param {object} msg + * @return {boolean} + * @public + */ + +function isFinished(msg) { + var socket = msg.socket + + if (typeof msg.finished === 'boolean') { + // OutgoingMessage + return Boolean(msg.finished || (socket && !socket.writable)) + } + + if (typeof msg.complete === 'boolean') { + // IncomingMessage + return Boolean(msg.upgrade || !socket || !socket.readable || (msg.complete && !msg.readable)) + } + + // don't know + return undefined +} + +/** + * Attach a finished listener to the message. + * + * @param {object} msg + * @param {function} callback + * @private + */ + +function attachFinishedListener(msg, callback) { + var eeMsg + var eeSocket + var finished = false + + function onFinish(error) { + eeMsg.cancel() + eeSocket.cancel() + + finished = true + callback(error) + } + + // finished on first message event + eeMsg = eeSocket = first([[msg, 'end', 'finish']], onFinish) + + function onSocket(socket) { + // remove listener + msg.removeListener('socket', onSocket) + + if (finished) return + if (eeMsg !== eeSocket) return + + // finished on first socket event + eeSocket = first([[socket, 'error', 'close']], onFinish) + } + + if (msg.socket) { + // socket already assigned + onSocket(msg.socket) + return + } + + // wait for socket to be assigned + msg.on('socket', onSocket) + + if (msg.socket === undefined) { + // node.js 0.8 patch + patchAssignSocket(msg, onSocket) + } +} + +/** + * Attach the listener to the message. + * + * @param {object} msg + * @return {function} + * @private + */ + +function attachListener(msg, listener) { + var attached = msg.__onFinished + + // create a private single listener with queue + if (!attached || !attached.queue) { + attached = msg.__onFinished = createListener(msg) + attachFinishedListener(msg, attached) + } + + attached.queue.push(listener) +} + +/** + * Create listener on message. + * + * @param {object} msg + * @return {function} + * @private + */ + +function createListener(msg) { + function listener(err) { + if (msg.__onFinished === listener) msg.__onFinished = null + if (!listener.queue) return + + var queue = listener.queue + listener.queue = null + + for (var i = 0; i < queue.length; i++) { + queue[i](err, msg) + } + } + + listener.queue = [] + + return listener +} + +/** + * Patch ServerResponse.prototype.assignSocket for node.js 0.8. + * + * @param {ServerResponse} res + * @param {function} callback + * @private + */ + +function patchAssignSocket(res, callback) { + var assignSocket = res.assignSocket + + if (typeof assignSocket !== 'function') return + + // res.on('socket', callback) is broken in 0.8 + res.assignSocket = function _assignSocket(socket) { + assignSocket.call(this, socket) + callback(socket) + } +}
@@ -0,0 +1,22 @@
+ +The MIT License (MIT) + +Copyright (c) 2014 Jonathan Ong me@jongleberry.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.
@@ -0,0 +1,80 @@
+# EE First + +[![NPM version][npm-image]][npm-url] +[![Build status][travis-image]][travis-url] +[![Test coverage][coveralls-image]][coveralls-url] +[![License][license-image]][license-url] +[![Downloads][downloads-image]][downloads-url] +[![Gittip][gittip-image]][gittip-url] + +Get the first event in a set of event emitters and event pairs, +then clean up after itself. + +## Install + +```sh +$ npm install ee-first +``` + +## API + +```js +var first = require('ee-first') +``` + +### first(arr, listener) + +Invoke `listener` on the first event from the list specified in `arr`. `arr` is +an array of arrays, with each array in the format `[ee, ...event]`. `listener` +will be called only once, the first time any of the given events are emitted. If +`error` is one of the listened events, then if that fires first, the `listener` +will be given the `err` argument. + +The `listener` is invoked as `listener(err, ee, event, args)`, where `err` is the +first argument emitted from an `error` event, if applicable; `ee` is the event +emitter that fired; `event` is the string event name that fired; and `args` is an +array of the arguments that were emitted on the event. + +```js +var ee1 = new EventEmitter() +var ee2 = new EventEmitter() + +first([ + [ee1, 'close', 'end', 'error'], + [ee2, 'error'] +], function (err, ee, event, args) { + // listener invoked +}) +``` + +#### .cancel() + +The group of listeners can be cancelled before being invoked and have all the event +listeners removed from the underlying event emitters. + +```js +var thunk = first([ + [ee1, 'close', 'end', 'error'], + [ee2, 'error'] +], function (err, ee, event, args) { + // listener invoked +}) + +// cancel and clean up +thunk.cancel() +``` + +[npm-image]: https://img.shields.io/npm/v/ee-first.svg?style=flat-square +[npm-url]: https://npmjs.org/package/ee-first +[github-tag]: http://img.shields.io/github/tag/jonathanong/ee-first.svg?style=flat-square +[github-url]: https://github.com/jonathanong/ee-first/tags +[travis-image]: https://img.shields.io/travis/jonathanong/ee-first.svg?style=flat-square +[travis-url]: https://travis-ci.org/jonathanong/ee-first +[coveralls-image]: https://img.shields.io/coveralls/jonathanong/ee-first.svg?style=flat-square +[coveralls-url]: https://coveralls.io/r/jonathanong/ee-first?branch=master +[license-image]: http://img.shields.io/npm/l/ee-first.svg?style=flat-square +[license-url]: LICENSE.md +[downloads-image]: http://img.shields.io/npm/dm/ee-first.svg?style=flat-square +[downloads-url]: https://npmjs.org/package/ee-first +[gittip-image]: https://img.shields.io/gittip/jonathanong.svg?style=flat-square +[gittip-url]: https://www.gittip.com/jonathanong/
@@ -0,0 +1,95 @@
+/*! + * ee-first + * Copyright(c) 2014 Jonathan Ong + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = first + +/** + * Get the first event in a set of event emitters and event pairs. + * + * @param {array} stuff + * @param {function} done + * @public + */ + +function first(stuff, done) { + if (!Array.isArray(stuff)) + throw new TypeError('arg must be an array of [ee, events...] arrays') + + var cleanups = [] + + for (var i = 0; i < stuff.length; i++) { + var arr = stuff[i] + + if (!Array.isArray(arr) || arr.length < 2) + throw new TypeError('each array member must be [ee, events...]') + + var ee = arr[0] + + for (var j = 1; j < arr.length; j++) { + var event = arr[j] + var fn = listener(event, callback) + + // listen to the event + ee.on(event, fn) + // push this listener to the list of cleanups + cleanups.push({ + ee: ee, + event: event, + fn: fn, + }) + } + } + + function callback() { + cleanup() + done.apply(null, arguments) + } + + function cleanup() { + var x + for (var i = 0; i < cleanups.length; i++) { + x = cleanups[i] + x.ee.removeListener(x.event, x.fn) + } + } + + function thunk(fn) { + done = fn + } + + thunk.cancel = cleanup + + return thunk +} + +/** + * Create the event listener. + * @private + */ + +function listener(event, done) { + return function onevent(arg1) { + var args = new Array(arguments.length) + var ee = this + var err = event === 'error' + ? arg1 + : null + + // copy args to prevent arguments escaping scope + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i] + } + + done(err, ee, event, args) + } +}
@@ -0,0 +1,64 @@
+{ + "name": "ee-first", + "description": "return the first event in a set of ee/event pairs", + "version": "1.1.1", + "author": { + "name": "Jonathan Ong", + "email": "me@jongleberry.com", + "url": "http://jongleberry.com" + }, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + } + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/jonathanong/ee-first.git" + }, + "devDependencies": { + "istanbul": "0.3.9", + "mocha": "2.2.5" + }, + "files": [ + "index.js", + "LICENSE" + ], + "scripts": { + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "gitHead": "512e0ce4cc3643f603708f965a97b61b1a9c0441", + "bugs": { + "url": "https://github.com/jonathanong/ee-first/issues" + }, + "homepage": "https://github.com/jonathanong/ee-first", + "_id": "ee-first@1.1.1", + "_shasum": "590c61156b0ae2f4f0255732a158b266bc56b21d", + "_from": "ee-first@1.1.1", + "_npmVersion": "1.4.28", + "_npmUser": { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + "maintainers": [ + { + "name": "jongleberry", + "email": "jonathanrichardong@gmail.com" + }, + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "dist": { + "shasum": "590c61156b0ae2f4f0255732a158b266bc56b21d", + "tarball": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,71 @@
+{ + "name": "on-finished", + "description": "Execute a callback when a request closes, finishes, or errors", + "version": "2.3.0", + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Jonathan Ong", + "email": "me@jongleberry.com", + "url": "http://jongleberry.com" + } + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/on-finished.git" + }, + "dependencies": { + "ee-first": "1.1.1" + }, + "devDependencies": { + "istanbul": "0.3.9", + "mocha": "2.2.5" + }, + "engines": { + "node": ">= 0.8" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "index.js" + ], + "scripts": { + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "gitHead": "34babcb58126a416fcf5205768204f2e12699dda", + "bugs": { + "url": "https://github.com/jshttp/on-finished/issues" + }, + "homepage": "https://github.com/jshttp/on-finished", + "_id": "on-finished@2.3.0", + "_shasum": "20f1336481b083cd75337992a16971aa2d906947", + "_from": "on-finished@>=2.3.0 <2.4.0", + "_npmVersion": "1.4.28", + "_npmUser": { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "jongleberry", + "email": "jonathanrichardong@gmail.com" + } + ], + "dist": { + "shasum": "20f1336481b083cd75337992a16971aa2d906947", + "tarball": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,16 @@
+1.0.1 / 2015-09-29 +================== + + * perf: enable strict mode + +1.0.0 / 2014-08-10 +================== + + * Honor `res.statusCode` change in `listener` + * Move to `jshttp` orgainzation + * Prevent `arguments`-related de-opt + +0.0.0 / 2014-05-13 +================== + + * Initial implementation
@@ -0,0 +1,22 @@
+(The MIT License) + +Copyright (c) 2014 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,76 @@
+# on-headers + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Execute a listener when a response is about to write headers. + +## Installation + +```sh +$ npm install on-headers +``` + +## API + +```js +var onHeaders = require('on-headers') +``` + +### onHeaders(res, listener) + +This will add the listener `listener` to fire when headers are emitted for `res`. +The listener is passed the `response` object as it's context (`this`). Headers are +considered to be emitted only once, right before they are sent to the client. + +When this is called multiple times on the same `res`, the `listener`s are fired +in the reverse order they were added. + +## Examples + +```js +var http = require('http') +var onHeaders = require('on-headers') + +http +.createServer(onRequest) +.listen(3000) + +function addPoweredBy() { + // set if not set by end of request + if (!this.getHeader('X-Powered-By')) { + this.setHeader('X-Powered-By', 'Node.js') + } +} + +function onRequest(req, res) { + onHeaders(res, addPoweredBy) + + res.setHeader('Content-Type', 'text/plain') + res.end('hello!') +} +``` + +## Testing + +```sh +$ npm test +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/on-headers.svg +[npm-url]: https://npmjs.org/package/on-headers +[node-version-image]: https://img.shields.io/node/v/on-headers.svg +[node-version-url]: http://nodejs.org/download/ +[travis-image]: https://img.shields.io/travis/jshttp/on-headers/master.svg +[travis-url]: https://travis-ci.org/jshttp/on-headers +[coveralls-image]: https://img.shields.io/coveralls/jshttp/on-headers/master.svg +[coveralls-url]: https://coveralls.io/r/jshttp/on-headers?branch=master +[downloads-image]: https://img.shields.io/npm/dm/on-headers.svg +[downloads-url]: https://npmjs.org/package/on-headers
@@ -0,0 +1,93 @@
+/*! + * on-headers + * Copyright(c) 2014 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Reference to Array slice. + */ + +var slice = Array.prototype.slice + +/** + * Execute a listener when a response is about to write headers. + * + * @param {Object} res + * @return {Function} listener + * @api public + */ + +module.exports = function onHeaders(res, listener) { + if (!res) { + throw new TypeError('argument res is required') + } + + if (typeof listener !== 'function') { + throw new TypeError('argument listener must be a function') + } + + res.writeHead = createWriteHead(res.writeHead, listener) +} + +function createWriteHead(prevWriteHead, listener) { + var fired = false; + + // return function with core name and argument list + return function writeHead(statusCode) { + // set headers from arguments + var args = setWriteHeadHeaders.apply(this, arguments); + + // fire listener + if (!fired) { + fired = true + listener.call(this) + + // pass-along an updated status code + if (typeof args[0] === 'number' && this.statusCode !== args[0]) { + args[0] = this.statusCode + args.length = 1 + } + } + + prevWriteHead.apply(this, args); + } +} + +function setWriteHeadHeaders(statusCode) { + var length = arguments.length + var headerIndex = length > 1 && typeof arguments[1] === 'string' + ? 2 + : 1 + + var headers = length >= headerIndex + 1 + ? arguments[headerIndex] + : undefined + + this.statusCode = statusCode + + // the following block is from node.js core + if (Array.isArray(headers)) { + // handle array case + for (var i = 0, len = headers.length; i < len; ++i) { + this.setHeader(headers[i][0], headers[i][1]) + } + } else if (headers) { + // handle object case + var keys = Object.keys(headers) + for (var i = 0; i < keys.length; i++) { + var k = keys[i] + if (k) this.setHeader(k, headers[k]) + } + } + + // copy leading arguments + var args = new Array(Math.min(length, headerIndex)) + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i] + } + + return args +}
@@ -0,0 +1,70 @@
+{ + "name": "on-headers", + "description": "Execute a listener when a response is about to write headers", + "version": "1.0.1", + "author": { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + "license": "MIT", + "keywords": [ + "event", + "headers", + "http", + "onheaders" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/on-headers.git" + }, + "dependencies": {}, + "devDependencies": { + "istanbul": "0.3.21", + "mocha": "2.3.3", + "supertest": "1.1.0" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "README.md", + "index.js" + ], + "engines": { + "node": ">= 0.8" + }, + "scripts": { + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "gitHead": "ab0156a979d72353cfe666cccb3639e016b00280", + "bugs": { + "url": "https://github.com/jshttp/on-headers/issues" + }, + "homepage": "https://github.com/jshttp/on-headers", + "_id": "on-headers@1.0.1", + "_shasum": "928f5d0f470d49342651ea6794b0857c100693f7", + "_from": "on-headers@>=1.0.1 <1.1.0", + "_npmVersion": "1.4.28", + "_npmUser": { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "jongleberry", + "email": "jonathanrichardong@gmail.com" + } + ], + "dist": { + "shasum": "928f5d0f470d49342651ea6794b0857c100693f7", + "tarball": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "readme": "ERROR: No README data found!" +}
@@ -0,0 +1,97 @@
+{ + "name": "morgan", + "description": "HTTP request logger middleware for node.js", + "version": "1.7.0", + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Jonathan Ong", + "email": "me@jongleberry.com", + "url": "http://jongleberry.com" + } + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/expressjs/morgan" + }, + "dependencies": { + "basic-auth": "~1.0.3", + "debug": "~2.2.0", + "depd": "~1.1.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + }, + "devDependencies": { + "istanbul": "0.4.2", + "mocha": "2.4.5", + "split": "1.0.0", + "supertest": "1.1.0" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "README.md", + "index.js" + ], + "engines": { + "node": ">= 0.8.0" + }, + "scripts": { + "test": "mocha --check-leaks --reporter spec --bail", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --check-leaks --reporter dot", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --check-leaks --reporter spec" + }, + "gitHead": "5da5ff1f5446e3f3ff29d29a2d6582712612bf89", + "bugs": { + "url": "https://github.com/expressjs/morgan/issues" + }, + "homepage": "https://github.com/expressjs/morgan", + "_id": "morgan@1.7.0", + "_shasum": "eb10ca8e50d1abe0f8d3dad5c0201d052d981c62", + "_from": "morgan@latest", + "_npmVersion": "1.4.28", + "_npmUser": { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + "maintainers": [ + { + "name": "defunctzombie", + "email": "shtylman@gmail.com" + }, + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "fishrock123", + "email": "fishrock123@rocketmail.com" + }, + { + "name": "jongleberry", + "email": "jonathanrichardong@gmail.com" + }, + { + "name": "mscdex", + "email": "mscdex@mscdex.net" + }, + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + } + ], + "dist": { + "shasum": "eb10ca8e50d1abe0f8d3dad5c0201d052d981c62", + "tarball": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz" + }, + "_npmOperationalInternal": { + "host": "packages-6-west.internal.npmjs.com", + "tmp": "tmp/morgan-1.7.0.tgz_1455857999079_0.07957377028651536" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz" +}
@@ -7,6 +7,8 @@ "dependencies": {
"mongoose": "~3.6.11", "express": "^4.7.1", "method-override": "^2.1.2", - "body-parser": "^1.5.1" + "body-parser": "^1.5.1", + "jsonwebtoken" : "latest", + "morgan" : "latest" } }
@@ -4,16 +4,26 @@ bodyParser = require("body-parser"),
methodOverride = require("method-override"), mongoose = require('mongoose'); + +var morgan = require('morgan'); +var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens +var config = require('./config'); // get our config file + + // Connection to DB -mongoose.connect('mongodb://localhost/users', function(err, res) { +mongoose.connect(config.database, function(err, res) { if(err) throw err; console.log('Connected to Database'); }); +app.set('superSecret', config.secret); // secret variable // Middlewares app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.use(methodOverride()); + +// use morgan to log requests to the console +app.use(morgan('dev')); // Import Models and controllers var userMdl = require('./models/userModel')(app, mongoose);@@ -31,33 +41,30 @@ app.use(router);*/
app.use(express.static(__dirname + '/web')); // API routes -//users routes -var usersRoute = express.Router(); +var apiRoutes = express.Router(); -usersRoute.route('/users') +apiRoutes.route('/users') .get(userCtrl.findAllUsers) .post(userCtrl.addUser); -usersRoute.route('/users/:id') +apiRoutes.route('/users/:id') .get(userCtrl.findById) .put(userCtrl.updateActivity) .delete(userCtrl.deleteActivity); -app.use('/api', usersRoute); +apiRoutes.route('/auth') + .post(userCtrl.login); -//thoughts routes -var thoughtsRoute = express.Router(); - -thoughtsRoute.route('/thoughts') +apiRoutes.route('/thoughts') .get(thoughtCtrl.findAllThoughts) .post(thoughtCtrl.addThought); -thoughtsRoute.route('/thoughts/:id') +apiRoutes.route('/thoughts/:id') .get(thoughtCtrl.findById) .put(thoughtCtrl.updateActivity) .delete(thoughtCtrl.deleteActivity); -app.use('/api', thoughtsRoute); +app.use('/api', apiRoutes); // Start server app.listen(3000, function() {