/node_modules/mongoose/lib/schema/date.js

https://bitbucket.org/coleman333/smartsite · JavaScript · 298 lines · 113 code · 41 blank · 144 comment · 24 complexity · 367983f377721c664c6677bbad95105a MD5 · raw file

  1. /*!
  2. * Module requirements.
  3. */
  4. var MongooseError = require('../error');
  5. var utils = require('../utils');
  6. var SchemaType = require('../schematype');
  7. var CastError = SchemaType.CastError;
  8. /**
  9. * Date SchemaType constructor.
  10. *
  11. * @param {String} key
  12. * @param {Object} options
  13. * @inherits SchemaType
  14. * @api public
  15. */
  16. function SchemaDate(key, options) {
  17. SchemaType.call(this, key, options, 'Date');
  18. }
  19. /**
  20. * This schema type's name, to defend against minifiers that mangle
  21. * function names.
  22. *
  23. * @api public
  24. */
  25. SchemaDate.schemaName = 'Date';
  26. /*!
  27. * Inherits from SchemaType.
  28. */
  29. SchemaDate.prototype = Object.create(SchemaType.prototype);
  30. SchemaDate.prototype.constructor = SchemaDate;
  31. /**
  32. * Declares a TTL index (rounded to the nearest second) for _Date_ types only.
  33. *
  34. * This sets the `expireAfterSeconds` index option available in MongoDB >= 2.1.2.
  35. * This index type is only compatible with Date types.
  36. *
  37. * ####Example:
  38. *
  39. * // expire in 24 hours
  40. * new Schema({ createdAt: { type: Date, expires: 60*60*24 }});
  41. *
  42. * `expires` utilizes the `ms` module from [guille](https://github.com/guille/) allowing us to use a friendlier syntax:
  43. *
  44. * ####Example:
  45. *
  46. * // expire in 24 hours
  47. * new Schema({ createdAt: { type: Date, expires: '24h' }});
  48. *
  49. * // expire in 1.5 hours
  50. * new Schema({ createdAt: { type: Date, expires: '1.5h' }});
  51. *
  52. * // expire in 7 days
  53. * var schema = new Schema({ createdAt: Date });
  54. * schema.path('createdAt').expires('7d');
  55. *
  56. * @param {Number|String} when
  57. * @added 3.0.0
  58. * @return {SchemaType} this
  59. * @api public
  60. */
  61. SchemaDate.prototype.expires = function(when) {
  62. if (!this._index || this._index.constructor.name !== 'Object') {
  63. this._index = {};
  64. }
  65. this._index.expires = when;
  66. utils.expires(this._index);
  67. return this;
  68. };
  69. /**
  70. * Check if the given value satisfies a required validator. To satisfy
  71. * a required validator, the given value must be an instance of `Date`.
  72. *
  73. * @param {Any} value
  74. * @param {Document} doc
  75. * @return {Boolean}
  76. * @api public
  77. */
  78. SchemaDate.prototype.checkRequired = function(value) {
  79. return value instanceof Date;
  80. };
  81. /**
  82. * Sets a minimum date validator.
  83. *
  84. * ####Example:
  85. *
  86. * var s = new Schema({ d: { type: Date, min: Date('1970-01-01') })
  87. * var M = db.model('M', s)
  88. * var m = new M({ d: Date('1969-12-31') })
  89. * m.save(function (err) {
  90. * console.error(err) // validator error
  91. * m.d = Date('2014-12-08');
  92. * m.save() // success
  93. * })
  94. *
  95. * // custom error messages
  96. * // We can also use the special {MIN} token which will be replaced with the invalid value
  97. * var min = [Date('1970-01-01'), 'The value of path `{PATH}` ({VALUE}) is beneath the limit ({MIN}).'];
  98. * var schema = new Schema({ d: { type: Date, min: min })
  99. * var M = mongoose.model('M', schema);
  100. * var s= new M({ d: Date('1969-12-31') });
  101. * s.validate(function (err) {
  102. * console.log(String(err)) // ValidationError: The value of path `d` (1969-12-31) is before the limit (1970-01-01).
  103. * })
  104. *
  105. * @param {Date} value minimum date
  106. * @param {String} [message] optional custom error message
  107. * @return {SchemaType} this
  108. * @see Customized Error Messages #error_messages_MongooseError-messages
  109. * @api public
  110. */
  111. SchemaDate.prototype.min = function(value, message) {
  112. if (this.minValidator) {
  113. this.validators = this.validators.filter(function(v) {
  114. return v.validator !== this.minValidator;
  115. }, this);
  116. }
  117. if (value) {
  118. var msg = message || MongooseError.messages.Date.min;
  119. msg = msg.replace(/{MIN}/, (value === Date.now ? 'Date.now()' : this.cast(value).toString()));
  120. var _this = this;
  121. this.validators.push({
  122. validator: this.minValidator = function(val) {
  123. var min = (value === Date.now ? value() : _this.cast(value));
  124. return val === null || val.valueOf() >= min.valueOf();
  125. },
  126. message: msg,
  127. type: 'min',
  128. min: value
  129. });
  130. }
  131. return this;
  132. };
  133. /**
  134. * Sets a maximum date validator.
  135. *
  136. * ####Example:
  137. *
  138. * var s = new Schema({ d: { type: Date, max: Date('2014-01-01') })
  139. * var M = db.model('M', s)
  140. * var m = new M({ d: Date('2014-12-08') })
  141. * m.save(function (err) {
  142. * console.error(err) // validator error
  143. * m.d = Date('2013-12-31');
  144. * m.save() // success
  145. * })
  146. *
  147. * // custom error messages
  148. * // We can also use the special {MAX} token which will be replaced with the invalid value
  149. * var max = [Date('2014-01-01'), 'The value of path `{PATH}` ({VALUE}) exceeds the limit ({MAX}).'];
  150. * var schema = new Schema({ d: { type: Date, max: max })
  151. * var M = mongoose.model('M', schema);
  152. * var s= new M({ d: Date('2014-12-08') });
  153. * s.validate(function (err) {
  154. * console.log(String(err)) // ValidationError: The value of path `d` (2014-12-08) exceeds the limit (2014-01-01).
  155. * })
  156. *
  157. * @param {Date} maximum date
  158. * @param {String} [message] optional custom error message
  159. * @return {SchemaType} this
  160. * @see Customized Error Messages #error_messages_MongooseError-messages
  161. * @api public
  162. */
  163. SchemaDate.prototype.max = function(value, message) {
  164. if (this.maxValidator) {
  165. this.validators = this.validators.filter(function(v) {
  166. return v.validator !== this.maxValidator;
  167. }, this);
  168. }
  169. if (value) {
  170. var msg = message || MongooseError.messages.Date.max;
  171. msg = msg.replace(/{MAX}/, (value === Date.now ? 'Date.now()' : this.cast(value).toString()));
  172. var _this = this;
  173. this.validators.push({
  174. validator: this.maxValidator = function(val) {
  175. var max = (value === Date.now ? value() : _this.cast(value));
  176. return val === null || val.valueOf() <= max.valueOf();
  177. },
  178. message: msg,
  179. type: 'max',
  180. max: value
  181. });
  182. }
  183. return this;
  184. };
  185. /**
  186. * Casts to date
  187. *
  188. * @param {Object} value to cast
  189. * @api private
  190. */
  191. SchemaDate.prototype.cast = function(value) {
  192. // If null or undefined
  193. if (value === null || value === void 0 || value === '') {
  194. return null;
  195. }
  196. if (value instanceof Date) {
  197. if (isNaN(value.valueOf())) {
  198. throw new CastError('date', value, this.path);
  199. }
  200. return value;
  201. }
  202. var date;
  203. if (typeof value === 'boolean') {
  204. throw new CastError('date', value, this.path);
  205. }
  206. if (value instanceof Number || typeof value === 'number') {
  207. date = new Date(value);
  208. } else if (typeof value.valueOf === 'function') {
  209. // support for moment.js. This is also the path strings will take because strings
  210. // have a `valueOf()`
  211. date = new Date(value.valueOf());
  212. } else {
  213. // fallback
  214. date = new Date(value);
  215. }
  216. if (!isNaN(date.valueOf())) {
  217. return date;
  218. }
  219. throw new CastError('date', value, this.path);
  220. };
  221. /*!
  222. * Date Query casting.
  223. *
  224. * @api private
  225. */
  226. function handleSingle(val) {
  227. return this.cast(val);
  228. }
  229. SchemaDate.prototype.$conditionalHandlers =
  230. utils.options(SchemaType.prototype.$conditionalHandlers, {
  231. $gt: handleSingle,
  232. $gte: handleSingle,
  233. $lt: handleSingle,
  234. $lte: handleSingle
  235. });
  236. /**
  237. * Casts contents for queries.
  238. *
  239. * @param {String} $conditional
  240. * @param {any} [value]
  241. * @api private
  242. */
  243. SchemaDate.prototype.castForQuery = function($conditional, val) {
  244. var handler;
  245. if (arguments.length !== 2) {
  246. return this._castForQuery($conditional);
  247. }
  248. handler = this.$conditionalHandlers[$conditional];
  249. if (!handler) {
  250. throw new Error('Can\'t use ' + $conditional + ' with Date.');
  251. }
  252. return handler.call(this, val);
  253. };
  254. /*!
  255. * Module exports.
  256. */
  257. module.exports = SchemaDate;