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