123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- 'use strict';
- // Load modules
- const Any = require('./any');
- const Ref = require('./ref');
- const Hoek = require('hoek');
- const Moment = require('moment');
- // Declare internals
- const 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 = (() => {
- const isoString = internals.isoDate.toString();
- return (date) => {
- return date && (date.toString() === isoString);
- };
- })();
- internals.Date = class extends Any {
- constructor() {
- super();
- this._type = 'date';
- }
- _base(value, state, options) {
- const result = {
- value: (options.convert && internals.Date.toDate(value, this._flags.format, this._flags.timestamp, this._flags.multiplier)) || value
- };
- if (result.value instanceof Date && !isNaN(result.value.getTime())) {
- result.errors = null;
- }
- else if (!options.convert) {
- result.errors = this.createError('date.strict', null, state, options);
- }
- else {
- let context = null;
- let type;
- if (internals.isIsoDate(this._flags.format)) {
- type = 'isoDate';
- }
- else if (this._flags.timestamp) {
- type = 'timestamp.' + this._flags.timestamp;
- }
- else if (this._flags.format) {
- type = 'format';
- context = { format: this._flags.format };
- }
- else {
- type = 'base';
- }
- result.errors = this.createError('date.' + type, context, state, options);
- }
- return result;
- }
- static toDate(value, format, timestamp, multiplier) {
- if (value instanceof Date) {
- return value;
- }
- if (typeof value === 'string' ||
- (typeof value === 'number' && !isNaN(value) && isFinite(value))) {
- if (typeof value === 'string' &&
- /^[+-]?\d+(\.\d+)?$/.test(value)) {
- value = parseFloat(value);
- }
- let 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 if (timestamp && multiplier) {
- date = new Date(value * multiplier);
- }
- else {
- date = new Date(value);
- }
- if (!isNaN(date.getTime())) {
- return date;
- }
- }
- return null;
- }
- format(format) {
- Hoek.assert(typeof format === 'string' || (Array.isArray(format) && format.every((f) => typeof f === 'string')), 'Invalid format.');
- const obj = this.clone();
- obj._flags.format = format;
- return obj;
- }
- iso() {
- const obj = this.clone();
- obj._flags.format = internals.isoDate;
- return obj;
- }
- timestamp(type) {
- type = type || 'javascript';
- const allowed = ['javascript', 'unix'];
- Hoek.assert(allowed.indexOf(type) !== -1, '"type" must be one of "' + allowed.join('", "') + '"');
- const obj = this.clone();
- obj._flags.timestamp = type;
- obj._flags.multiplier = type === 'unix' ? 1000 : 1;
- return obj;
- }
- _isIsoDate(value) {
- return internals.isoDate.test(value);
- }
- };
- internals.compare = function (type, compare) {
- return function (date) {
- const isNow = date === 'now';
- const isRef = Ref.isRef(date);
- if (!isNow && !isRef) {
- date = internals.Date.toDate(date);
- }
- Hoek.assert(date, 'Invalid date format');
- return this._test(type, date, function (value, state, options) {
- let compareTo;
- if (isNow) {
- compareTo = Date.now();
- }
- else if (isRef) {
- compareTo = internals.Date.toDate(date(state.parent, options));
- if (!compareTo) {
- return this.createError('date.ref', { ref: date.key }, state, options);
- }
- compareTo = compareTo.getTime();
- }
- else {
- compareTo = date.getTime();
- }
- if (compare(value.getTime(), compareTo)) {
- return value;
- }
- return this.createError('date.' + type, { limit: new Date(compareTo) }, state, options);
- });
- };
- };
- internals.Date.prototype.min = internals.compare('min', (value, date) => value >= date);
- internals.Date.prototype.max = internals.compare('max', (value, date) => value <= date);
- module.exports = new internals.Date();
|