'use strict';
var assert = require('assert');
var util = require('util');
var ut = require('utjs');
var Type = require('./Type');
/**
* Generates a schema object that matches a date type.
*
* @constructor
* @extends Type
*/
function DateType() {
DateType.super_.call(this, this._hooks());
}
util.inherits(DateType, Type);
/**
* Specifies the oldest date allowed.
* @param {Date} date The oldest date allowed.
* @return {DateType} The class reference so multiple calls can be chained.
*/
DateType.prototype.min = function (date) {
date = this._toDate(date);
assert(date !== null, 'date must be a Date, number or ISO string');
this._rules.min = date;
this._minTs = date.getTime();
return this;
};
/**
* Specifies the latest date allowed.
* @param {Date} date The latest date allowed.
* @return {DateType} The class reference so multiple calls can be chained.
*/
DateType.prototype.max = function (date) {
date = this._toDate(date);
assert(date !== null, 'date must be a Date, number or ISO string');
this._rules.max = date;
this._maxTs = date.getTime();
return this;
};
/**
* Requires the string value to be in valid ISO 8601 date format.
* @return {DateType} The class reference so multiple calls can be chained.
*/
DateType.prototype.iso = function () {
this._rules.iso = true;
return this;
};
/**
* Requires the value to be a timestamp interval from Unix Time.
* @param {String} [type] The type of timestamp (allowed values are unix or javascript [default]).
* @return {DateType} The class reference so multiple calls can be chained.
*/
DateType.prototype.timestamp = function (type) {
type = type !== undefined ? type : 'javascript';
assert(type === 'javascript' || type === 'unix', 'type must be unix or javascript');
this._rules.timestamp = type;
return this;
};
DateType.prototype._validate = function (value) {
var rules = this._rules;
if (value instanceof Date === false) {
if (rules.timestamp !== undefined && typeof value === 'number') {
value = this._toDate(value);
} else if (rules.iso && ut.isDateString(value)) {
value = this._toDate(value);
} else {
return !rules.required && value === undefined;
}
}
var min = rules.min;
var max = rules.max;
var valueTs = value.getTime();
if (min !== undefined && valueTs < this._minTs ||
max !== undefined && valueTs > this._maxTs) {
return false;
}
return rules.forbidden ? false : true;
};
DateType.prototype._toDate = function (value) {
var rules = this._rules;
if (value instanceof Date) {
return value;
} else if (typeof value === 'number') {
value *= rules.timestamp === 'unix' ? 1000 : 1;
return new Date(value);
} else if (ut.isDateString(value)) {
return new Date(value);
}
return null;
};
DateType.prototype._hooks = function () {
return {
post: function (rules) {
if (rules !== undefined) {
if (rules.min !== undefined) {
this._minTs = rules.min.getTime();
}
if (rules.max !== undefined) {
this._maxTs = rules.max.getTime();
}
}
}
};
};
/**
* Creates and returns a DateType object.
* @return {DateType} The DateType object.
* @global
* @alias date
*/
module.exports = function date() {
return new DateType();
};